Error: Argument Type Double/String etc. Does Not Conform to Expected Type "Anyobject"

Why is casting a struct to AnyObject not a compile error in swift?

This is a feature to facilitate passing to Cocoa. Any struct can be wrapped into a SwiftValue reference type. If you print type(of: object) you'll see the wrapper.

I don't think there is any contract for "expecting a reference type." More importantly, while "value types" and "reference types" exist in Swift, what really matter is value and reference semantics, which are not expressible in the language. You can create value semantics in reference types and reference semantics in value types, so the Swift type system really isn't of any help in that regard.

The important point here is that you only get this unusual behavior if you explicitly request it by asking for as AnyObject. There are very few reason to write that, and if you are, you had better know exactly what you're doing.

Are there any concrete examples when using the Any type is a good solution?

When should I use [Any]?

Any is an abstract type that all other types implicitly conform to. Because it could be anything – it must be guaranteed to do nothing.

For that very reason, typing a variable as Any is nonsensical. If I define this:

let itCouldBeAnything : Any = "Actually it's a string"

It now can't do anything (without type casting):

Sample Image

You should always use the most descriptive type available when defining something, and because of Any's abstract nature, there will always be a more descriptive type available – in this case, String should've been used.

Now let’s think about arrays. As you say, Apple demonstrates that you can use an array of Any to mix together different types.

var things = [Any]()

things.append(0)
things.append(0.0)
things.append(42)
things.append(3.14159)
things.append("hello")
things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman"))

Great. But what does this array actually represent? It’s just a collection of junk – the programming equivalent of the backseat of my car.

If we try and do something with one of the elements...

Sample Image

We can’t. It could be anything – so we can’t do anything with it. Sure, we can type cast the elements with a switch or if statement to handle the different possibilities – but all we’ll succeed in doing there is splitting our array back into distinct types. So what was the point in using [Any] to begin with?

An array should always represent a collection of related data. There’s no point of an array if the elements share nothing in common. If the different types that the array can store have common functionality, then you should define a protocol with this common functionality:

protocol ACommonProtocol {
// define common functionality
}

We can then conform the types that the array can store to it:

extension Int : ACommonProtocol {}
extension Double : ACommonProtocol {}
extension String : ACommonProtocol {}
extension Movie : ACommonProtocol {}

Now our array can be of type [ACommonProtocol]. This is a significant improvement from Any, we’ve narrowed the concrete types that the elements could be down to 4 – and we can now use any common functionality that we define in the protocol on the elements without type-casting. Our elements also are now explicitly related, which actually gives the array some meaning (assuming the protocol represents a meaningful concept).

If the different types that the array can store don't have any common functionality, or cannot conform to protocols (such as tuples and functions), but are still related in some meaningful way – then another way of expressing this relationship is through using an enum with associated values:

// obviously this enum (and possibly its cases) should have a far better names
enum IntDoubleStringOrMovie {
case int(Int)
case double(Double)
case string(String)
case movie(Movie)
}

Now our array can be of type [IntDoubleStringOrMovie] – which has the added benefit of allowing us to use an exhaustive switch in order to determine the element type:

for element in array {
switch element {
case let .int(int):
print(int)
case let .double(double):
print(double)
case let .string(string):
print(string)
case let .movie(movie):
print(movie)
}
}

So for this reason, you should never ever have to use [Any] in Swift. If you ever find yourself in a situation of using [Any], you should be re-considering your data structure. Whether that involves splitting the array up into sub-arrays, conforming the elements to a common protocol (if they have common functionality), using an enum with associated values (if they have no common functionality) or using a different collection type altogether, is entirely up to you.

But what about interfacing with Objective-C?

Any is sometimes necessary for bridging with Objective-C’s inferior type system – and therefore you may well find yourself using [Any] with Objective-C APIs, which is acceptable (although with the bridging of Objective-C's lightweight generics to Swift, it should be uncommon).

The only thing I would say about this is once you’re back in your Swift logic, you should always convert an [Any] back to a meaningful array type through type casting, or unpacking it into a more appropriate data structure. You shouldn’t sacrifice type safety in Swift just because Objective-C lacks in that regard.

But what about [AnyObject]?

AnyObject is pretty much as vague as Any in pure Swift. The only thing it guarantees is that it’s a class. However, as of Swift 3, anything can be bridged to Objective-C by being boxed in a _SwiftValue. For this reason, [AnyObject] is just as (if not more) questionable as [Any].

AnyObject and Any in Swift

AnyObject is only for reference types (classes), Any is for both value and reference types.

So you should go for [String: Any].

Type Casting for Any and AnyObject

Swift provides two special types for working with nonspecific types:

  • Any can represent an instance of any type at all, including function
    types.
  • AnyObject can represent an instance of any class type.

NOTE:

Use Any and AnyObject only when you explicitly need the behavior and
capabilities they provide. It is always better to be specific about
the types you expect to work with in your code.

From The Swift Programming Language:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TypeCasting.html#//apple_ref/doc/uid/TP40014097-CH22-ID342

-

Also note that when you work with Cocoa API, it's common to receive an Array of AnyObject, this is because Objective-C arrays are NOT typified.
So you need to cast them to the array type you expect.

-

EDIT: (december 22, 2015)

On the last statement, note that this is changing with Swift 2.0 and Xcode 7.

Apple has introduced ‘Lightweight’ generics in Objective-C so lots of Cocoa APIs now already returns the correct type.

EDIT: (october 18, 2016)

Note that, as of Swift 3.0, Objective-C ids are now imported as Any, not anymore as AnyObject.

Swift: Cannot assign a value of type 'Any' to a value of type 'AnyObject?'

If you know that the type is always of type AnyObject you can use a forced cast:

prefObj[key] = value as! AnyObject

Otherwise use an optional cast with as? or change the function signature to:

func updateParse(className: String, whereKey: String, equalTo: String, updateData: Dictionary<String, AnyObject>)

Swift sorted by error: Cannot convert value of type 'CGFloat?' to expected argument type 'Self'

The frame property in ScannedFact is optional, hence you might wanna provide a default value when there isn't any frame available or when the frame property is nil. You cannot sort two objects comparing nil, so you either need to unwrap or give default values, like this:

func getSortedData(data:[(String, ScannedFacts)]) -> [(String, ScannedFacts)] {
return data.sorted(by: {$0.1.frame?.minX ?? 0 < $1.1.frame?.minX ?? 0 })
}

How to convert RealmOptional to Int or Float in Swift?

Lets assume your RealmOptional<Float>() variable is named myFloat. Then, use the getter for the RealmOptional:s (see this git entry for Realm) underlying value, .value, rather then checking the RealmOptional itself:

var value = myFloat.value // value variable now of type Float

Below follows and explanation of why the AnyObject? switches doesn't behave as you expect:

From Apples Language Guide - Type Casting:

Type Casting for Any and AnyObject

Swift provides two special type aliases for working with non-specific
types:

  • AnyObject can represent an instance of any class type.
  • Any can represent an instance of any type at all, including function types.

Hence, the AnyObject type can can hold instances of any class type, but the fundamental numeric types (Int, Double etc) in Swift are not of class type, but of structure type.

In the switch in your example, the AnyObject instance is not inferred but cast to the first possible successful downcast, which will be whatever case you put top-most that is of a numeric type. Hence, if you change the ordering of your case:s in the switch, the casting will change.

let value: AnyObject? = 30.0
// try change the order
switch value {
case is String: print("string");
case is Float: print("float"); // hits `Float` downcast first -> prints float
case is Int: print("int");
default: print("other")
}

Now, you could, however, cast your AnyObject to an NSNumber (class instance), and continue from there. From Working with Cocoa Data Types documentation:

Instances of the Swift numeric structure types, such as Int, UInt,
Float, Double, and Bool, cannot be represented by the AnyObject type,
because AnyObject only represents instances of a class type. However,
when bridging to Foundation is enabled, Swift numeric values can be
assigned to constants and variables of AnyObject type as bridged
instances of the NSNumber class.

Note however that NSNumber is fundamentally different from the Swift numeric types (Int, Double etc) in that the former hold any kind of number, and allows us to cast this number to different type of numeric types. However, we cannot easily infer which type a specific NSNumber instance should be cast to, but we could implement our own (not so pretty) specification as how to infer different NSNumber to different swift fundamental numeric types.

However, before proceeding with NSNumber hacking:

From above, the core problem is that your value property is of type AnyObject?. Could you please post the code that lead to value being of type AnyObject?. Possibly the casting to Int, Float and so on if not necessary if using the getter of the RealmOptional (hence no need to casting RealmOptional<T>() to AnyObject??).



Related Topics



Leave a reply



Submit