2

I'm a bit confused by the usage of AnyObject. Let me provide a few examples.

AnyObject

NSObject() is AnyObject

^ true (as expected)

class MyClass {}
MyClass() is AnyObject

^ true (as expected)

class MyClass {}
MyClass.self is AnyObject

^ true (as expected)

String() is AnyObject

^ true (as NOT expected)

struct MyStruct {}
MyStruct() is AnyObject

^ true (as NOT expected; String appears to be a struct)

String.self is AnyObject

^ false (as expected)

A snippet from Apple's documentation regarding AnyObject:

AnyObject can be used as the concrete type for an instance of any class, class type, or class-only protocol.

Why is an instance of struct is regarded as an AnyObject?

Alex Larson
  • 137
  • 1
  • 7

2 Answers2

3

Ugh, this is one of my gripes with Swift. It's an Objective C interop feature, which although useful, is too implicit/mysterious. This implicit boxing behaviour only happens when Foundation is imported, and only on systems with ObjC support (Apple's platforms).

Some Swift types bridge to specific ObjC counterparts, like NSString, NSNumber, NSArray, NSDictionary, etc. All other swift value types (like structs and tuples) are capable of being wrapped in a private ObjC class called _NSSwiftValue, which makes it possible to hand them off to ObjC APIs.

The most confusing thing is that the object has an ill-defined identity (object address) as far as Objective C is concerned, and if your type doesn't conform to Hashable, then the Hash value of the object is also ill-defined, which can lead to all kinds of hard-to-nail-down bugs.

Alexander
  • 59,041
  • 12
  • 98
  • 151
  • Thank you for your answer! I can understand how that might apply to String/Int/etc as there are equivalent types in Objective-C. But - why would it happen with any arbitrary struct (like MyStruct). Is it bridging my struct into a NSDictionary? – Alex Larson Feb 03 '20 at 21:00
  • 1
    @AlexLarson No, it's wrapping it in a box called `_NSSwiftValue`, an `NSObject` subclass whose only instance variable is the swift value typed being boxed up. – Alexander Feb 03 '20 at 21:01
  • Ohhhh! I misread. Thank you for the clarification! – Alex Larson Feb 03 '20 at 21:14
1

So basically String has an bridging connection to NSString, which is an NSObject. If we take the apple documentation at This place We can see that it's a typedef struct or typealias if you so will. And if we move on to look over here and scroll down in the list, we will see that in the previous link the CFStringRef as a struct is bridged to NSString as a class

Further down in Xcode we can see the documentation for String

Any String instance can be bridged to NSString using the type-cast operator (as), and any String instance that originates in Objective-C may use an NSString

Which basically tells us that you can throw an String class to an String struct without any problem because they are basically the same

Vollan
  • 1,887
  • 11
  • 26