Alak
Alak

Reputation: 1349

AnyObject and Any in Swift

I don't understand when to use AnyObject and when to use Any in Swift.

In my case, I've a Dictionary

[String: ???]

??? : Can be Int, Double, Float, String, Array, Dictionary

Can someone explain me the difference between Any and AnyObject and which one to use in my case.

Upvotes: 106

Views: 39723

Answers (6)

NSPratik
NSPratik

Reputation: 4846

AnyObject —> Reference type

Any —> Reference type & Value type

In Objective-C, there was no concept of value types, everything was reference type. And there was id type in Objective-C same like Any in Swift.

In Swift 2, Apple introduce AnyObject type (reference type) to work with id type (also reference type) of Objective-C.

Now there were issues, wrong behaviour while working with both Swift and Objective-C code in same project, because Swift mostly supports value types. When we expected value types in Swift, still it was giving reference type.

So Apple introduced Any in Swift 3.

Tip: Be as specific as we can, means avoid using Any and AnyObject and specify a exact class if possible like Int, String, Employee etc..

Then what is the difference between Any & Generic types?

Well, Generic type has benefits of type safety and constraints.

You can see in the following example, if we would have array of type Any, then we could also have added String (wrong input). Also we can’t use + operator on array items as they would been Any, but if we have Stack<Int>, we can do + (addition) operation.

enter image description here

Upvotes: 0

Blazej SLEBODA
Blazej SLEBODA

Reputation: 9925

By the default we should use "Any" and if we need more precision then we can chose more constrained types like AnyHashable, AnyObject, AnyClass, CustomType etc.

AnyObject should be used when sanding an object to frameworks which were written in Objective-C like UIKit and Foundation.

AnyObject accepts an instance of a class types and instances of types like enum, struct and optional class types objects are not accepted:

class CustomType {
   var instanceArg1: Int
   var instanceArg2: String
   static var classArg1: Int
}

Particularity of the AnyObject type is that an object of this type has access to all @objc methods and variables by autocompletion. If UIKit or Foundation are imported then the AnyObject instance object has access to all variables and methods of all Foundation objects by autocompletion.

the code below, compiles but crashes the app in runtime first of all due to the fact that given argument is of type String and not of UITableView and there is no a method tableView(_:numberOfRowsInSection) defined in String type.

import UIKit

class CustomType {

    func customMethod(arg1: AnyObject) {
        let tableView = UITableView()
        let numberOfRows = arg1.tableView(tableView, numberOfRowsInSection: 0)
    }
}

Upvotes: 1

Ved Rauniyar
Ved Rauniyar

Reputation: 1589

Check this SO answer:

Generics are type safe, meaning if you pass a string as a generic and try to use as a integer the compiler will complain and you will not be able to compile your (which is good). (This happens because Swift is using Static typing, and is able to give you a compiler error). If you use AnyObject the compiler has no idea is this object can be treated as a String or as an Integer and basically will allow you to do whatever you want with it (which is bad) as if you try to use an object that has been passed as a String when it is an Integer the application will crash. (This happens because Swift is using Dynamic typing and will only give you a runtime error)

Upvotes: 2

Rohit Sisodia
Rohit Sisodia

Reputation: 895

According to Apple’s Swift documentation,

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

For more details please check this: Blog

Upvotes: 4

Teejay
Teejay

Reputation: 7469

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.

Upvotes: 129

vacawama
vacawama

Reputation: 154593

Whether you use Any or AnyObject depends on your intended use:

If your dictionary will be used only within Swift code, then you should use Any because your types (Int, Double, Float, String, Array, and Dictionary) are not objects.

If you will be passing your dictionary to Objective-C routines that expect an NSDictionary, then you should use AnyObject.

When you import Foundation or import UIKit or import Cocoa, it is possible to declare your array as [String: AnyObject], but in this case Swift is treating your Int, Double, Float literals as NSNumber, your Strings as NSString, your Arrays as NSArray, and your dictionaries as NSDictionary, all of which are objects. A dictionary using AnyObject as the value type is convertible to NSDictionary, but one using Any is not.

Upvotes: 53

Related Questions