AnyObject, Any, any: AnyObject.
Sergey Leschev
Posted on December 17, 2022
AnyObject is a protocol to which all classes implicitly conform. In fact, the standard library contains a type alias AnyClass representing AnyObject.Type.
print(AnyObject.self) // Prints: AnyObject
print(AnyClass.self) // Prints: AnyObject.Type
All classes, class types, or class-only protocols can use AnyObject as their concrete type. To demonstrate, you could create an array of different types:
let imageView = UIImageView(image: nil)
let viewController = UIViewController(nibName: nil, bundle: nil)
let mixedArray: [AnyObject] = [
// We can add both `UIImageView` and `UIViewController` to the same array
// since they both cast to `AnyObject`.
imageView,
viewController,
// The `UIViewController` type conforms implicitly to `AnyObject` and can be added as well.
UIViewController.self
]
Only classes conform to AnyObject, meaning that you can use it to restrict protocols to be implemented by reference types only:
protocol MyProtocol: AnyObject { }
You can use AnyObject if you need the flexibility of an untyped object. I could give examples of using a collection of any objects that you can cast back to a concrete type when used, but I would like to suggest something different instead.
I can't remember using AnyObject in any of my projects, since I was always able to use concrete types instead. Doing so also leads to more readable code that is easier to understand by fellow developers. To demonstrate this to you, I've created this example method which configures an image into a destination container:
func configureImage(_ image: UIImage,
in imageDestinations: [AnyObject]) {
for imageDestination in imageDestinations {
switch imageDestination {
case let button as UIButton:
button.setImage(image, for: .normal)
case let imageView as UIImageView:
imageView.image = image
default:
print("Unsupported image destination")
break
}
}
}
By using AnyObject as our destination, we always need to cast and consider casting failures using the default implementation. My preference would always be to rewrite this using concrete protocols instead:
// Create a protocol to act as an image destination.
protocol ImageContainer {
func configureImage(_ image: UIImage)
}
// Make both `UIButton` and `UIImageView` conform to the protocol.
extension UIButton: ImageContainer {
func configureImage(_ image: UIImage) {
setImage(image, for: .normal)
}
}
extension UIImageView: ImageContainer {
func configureImage(_ image: UIImage) {
self.image = image
}
}
// Create a new method using the protocol as a destination.
func configureImage(_ image: UIImage, into destinations: [ImageContainer]) {
for destination in destinations {
destination.configureImage(image)
}
}
The resulting code is cleaner, readable, and no longer requires handling unsupported containers. Instances are required to conform to the ImageContainer protocol to be able to receive the configured image.
Next Article: Any
Contacts
I have a clear focus on time-to-market and don't prioritize technical debt. And I took part in the Pre-Sale/RFX activity as a System Architect, assessment efforts for Mobile (iOS-Swift, Android-Kotlin), Frontend (React-TypeScript) and Backend (NodeJS-.NET-PHP-Kafka-SQL-NoSQL). And I also formed the work of Pre-Sale as a CTO from Opportunity to Proposal via knowledge transfer to Successful Delivery.
🛩️ #startups #management #cto #swift #typescript #database
📧 Email: sergey.leschev@gmail.com
👋 LinkedIn: https://linkedin.com/in/sergeyleschev/
👋 LeetCode: https://leetcode.com/sergeyleschev/
👋 Twitter: https://twitter.com/sergeyleschev
👋 Github: https://github.com/sergeyleschev
🌎 Website: https://sergeyleschev.github.io
🌎 Reddit: https://reddit.com/user/sergeyleschev
🌎 Quora: https://quora.com/sergey-leschev
🌎 Medium: https://medium.com/@sergeyleschev
🖨️ PDF Design Patterns: Download
Posted on December 17, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.