1

I'm working with something trivialized to this:

func isAnyObject<T>(someObject: T) {
    if let object = someObject as? AnyObject {
        // do something
    } else {
        // do something else
    }
}

Which gives me the compiler warnings:

  1. Conditional cast from 'T' to 'AnyObject' always succeeds
  2. Non-optional expression of type 'AnyObject' used in a check for optionals

I understand why the cast always succeeds, but I don't know what to do to fix it. I tried changing line 2 to if let object = foo as AnyObject? but when I pass a struct through the function, it still gets into the 'if' block. What am I missing here?

Steals
  • 117
  • 1
  • 8
  • Why are you casting at all? – Alexander Oct 28 '16 at 22:50
  • P.s., don't write `-> Void` in function signatures. – Alexander Oct 28 '16 at 22:51
  • Oops. I don't know if I completely understand the purpose of the cast, however, for my own intentions, I'm just seeing what it would take for a struct object to be passed and for it to hit the 'else' block – Steals Oct 28 '16 at 22:55
  • 1
    Possible duplicate of [Check if \`Any\` value is object](http://stackoverflow.com/questions/39184911/check-if-any-value-is-object) – Hamish Oct 29 '16 at 06:08
  • Also related: http://stackoverflow.com/questions/39033194/anyobject-not-working-in-xcode8-beta6 – Martin R Oct 29 '16 at 06:13

2 Answers2

0

Actually I can't recreate the errors you're exhibiting. However, the compiler does complain about the obvious errors in the parameter of the function.

import Foundation

func isAnyObject<T>( _ someObject: T) {
    if let object = someObject as? AnyObject {
        print("It's an AnyObject: \(object)")
    } else {
        print("It's not an AnyObject.")
    }
}

let classObject: NSString = "This is an NSString Object"
let structInstance: String = "This is a Swift String Instance"

isAnyObject(classObject) // It's an AnyObject: This is an NSString Object
isAnyObject(structInstance) // It's not an AnyObject.

You can try it online, here.

Alexander
  • 59,041
  • 12
  • 98
  • 151
  • ah apologies. In the attempt to trivialize my code snippet, i introduced a lot of typos. While I didn't get any warnings through the sandbox, plugging that same code into playground or XCode still gets me the same two warnings I listed above. – Steals Oct 28 '16 at 23:06
  • Interesting, I'm getting the warnings in Xcode too. This behaviour is probably a side effect for the automatic boxing Swift does for struct types. – Alexander Oct 28 '16 at 23:19
0

You can check if the type of the variable is AnyObject. If so its a reference type. If not its a value type. I also get a warning in the playground, but the warning is wrong. The code below produces false, false, false, false, true so clearly the function works and the test is not always true as the warning says. This is a bug.

    func isReferenceType<T>(someObject: T) -> Bool {
        return type(of: someObject) is AnyObject
    }

    //Values
    print(isReferenceType(someObject: "a"))
    print(isReferenceType(someObject: 1))
    print(isReferenceType(someObject: Int?(0)))
    print(isReferenceType(someObject: {print("1")}))
    //Reference
    print(isReferenceType(someObject: UIView()))
Josh Homann
  • 15,933
  • 3
  • 30
  • 33
  • Thanks. This was what was throwing me for a loop. I was under the impression that a Struct can not be cast to AnyObject but when I created a struct and tried this: `SomeStruct() is AnyObject` it was returning true. Any idea why this is the case? – Steals Oct 28 '16 at 23:16
  • You can just write `someObject is AnyObject`, without `type(of:)` – Alexander Oct 28 '16 at 23:18
  • Also, I wonder if there's a problem I wrote with this line `if let object = someObject as? AnyObject` because even with testing my 'isAnyObject' with a UIView, I'm still getting inside the 'if' statement – Steals Oct 28 '16 at 23:21
  • @AlexanderMomchliov if you leave out type of you get true, true, true, true, true which is weird because only one of those is a reference type. thats why you need the type(of:). Its not the same. – Josh Homann Oct 28 '16 at 23:23
  • @JoshHomann interesting, so any autoboxing behaviour that's occurring only effects instances of structs, but not the struct type itself – Alexander Oct 28 '16 at 23:26
  • Yes there is definitely some boxing magic going on here. You can see it if you add a print (type(of:someObject as AnyObject)) statement. _NSContiguousString, _SwiftTypePreservingNSNumber, _SwiftValue, _SwiftValue, UIView. – Josh Homann Oct 28 '16 at 23:35