1

The following code works:

nil as! String?
"muffin" as! String?

Therefore I also expect this to work:

var magicArray: [Any?] = ["Muffin", nil, 3]

class Box<T> {

    var index: Int

    init(index: Int){
        self.index = index
    }

    func get() -> T {
        return magicArray[index] as! T //crash
    }

}

But neither

let box = Box<String?>(index: 0)
box.get()

nor

let box = Box<String?>(index: 1)
box.get()

works as expected. The program crashes at the cast in get(). This however works:

let box = Box<Int>(index: 2)
box.get()

I need to be able to cast a Any? value to T inside my class where T can be any type, including optionals. The Any? actually comes from an array of Any? so there is no other way of verifying it’s of the correct type T.

Is this possible?

idmean
  • 14,540
  • 9
  • 54
  • 83
  • 1
    Why do you need this? – Adam Sep 25 '15 at 16:25
  • 1
    @Adam It’s needed for an ORM library. Just believe me, I need it. – idmean Sep 25 '15 at 16:27
  • 1
    Saying "Any" with regard to a generic seems to completely miss the point of generics. – matt Sep 25 '15 at 16:54
  • @matt I’ve updated my answer to add more context. Am I really missing the point of generics? – idmean Sep 25 '15 at 17:03
  • The question title should be something around "How to cast any? to optional". [This should give you a good idea](http://stackoverflow.com/questions/27989094/how-to-unwrap-an-optional-value-from-any-type/32780793#32780793) – Maic López Sáenz Sep 26 '15 at 05:51
  • @LopSae Thanks for your help. Actually I think now my design is simply bad, I’ll try to find a way so that I don’t have to deal with `[Any?]` arrays. – idmean Sep 26 '15 at 07:09

1 Answers1

0

If you need a generic wrapper, this should work for you:

final class Wrapper<T> {
    final let wrappedValue: T
    init(theValue: T) {
        wrappedValue = theValue
    }
}

You can replace let with var to make it mutable.

Edit:

This is the code I used to test it on a playground.

var s : Any?

s = "some string"

let w = Wrapper(theValue: s)

w.wrappedValue

let int = 3

let w2 = Wrapper(theValue: int)

w2.wrappedValue

w2.wrappedValue = 3

let array : [Any?] = [s, int, nil, "abc", NSObject()]

for obj in array {
    let wrapper = Wrapper(theValue: obj)
}
Adam
  • 26,549
  • 8
  • 62
  • 79
  • I can’t see any cast from `Any?` to `T`. I don’t just need a wrapper, I need a wrapper that can cast `Any?` values to `T`. – idmean Sep 25 '15 at 16:28
  • You haven't specified your requirements. Why do you need to cast from `Any?` to `T` ? – Adam Sep 25 '15 at 16:31
  • Sorry, I thought that was clear from my example. I need to be able to cast a `Any?` value to `T` inside my class where `T` can be any type, including optionals. Explaining why I’ve got a `Any?` value is way to complicated. – idmean Sep 25 '15 at 16:33
  • The `Any?` comes from an array of `Any?` so there is no other way of verifying it’s of the correct type `T`. – idmean Sep 25 '15 at 16:36
  • The wrapper will work with an array of `Any?` and use the right type for each of them. I just tested it with strings, ints, optional or not, and also with an array of `Any?`. Worked perfectly. Not sure if I understand why you need to cast it to some other type. In my class, `T` is a generic type. It is determined when the wrapper object is constructed and the same type is returned. – Adam Sep 25 '15 at 16:48
  • Sure. Edited the answer. – Adam Sep 25 '15 at 16:52
  • Ok, I was too unclear again. The wrapper get’s an `Any?` value and then **casts this value on request**. The wrapper is given a `Any?` and gives the value back as `T`, if he is request to do so. That all happens at run time. That’s the way I need to do it. If my explanation is still to vague I will try to provide update my answer to provide a more realistic example why I need this. – idmean Sep 25 '15 at 16:54
  • I’ve updated my question, I hope it’s now more clear. Anyways thanks for trying to help so far. – idmean Sep 25 '15 at 17:06
  • I have seen your edit. It is not possible and for me, it doesn't make sense. Hope this answers your question. – Adam Sep 25 '15 at 17:26
  • How do you know it’s not possible? Is there any Swift reference describing this? Otherwise it’s more likely to be a bug in Swift itself. – idmean Sep 25 '15 at 17:28
  • Not possible because you are trying to cast different values to a single type. How would you expect it to work. You want `String` to magically convert into `Int` or `UIView`? Not gonna happen. – Adam Sep 25 '15 at 17:32
  • I would not expect this too work if that were not that two lines of code at the beginning of my question that do actually work. – idmean Sep 25 '15 at 17:34
  • They do, because both `nil` and `"muffin"` are proper `String?` values. If you try `"muffin" as! UIView?`, it will crash. – Adam Sep 25 '15 at 17:37
  • But if I store a `String` in an `Any?` variable it becomes an invalid `String?` value, or what are you trying to tell me? The problem is Swift itself. It does not expect `T` to be an optional and therefore does not do an automatic conversion to the optional, because `String` is as you said not `Optional`. (If it expects an optional is seems to try to do a conversion.) – idmean Sep 25 '15 at 17:42