Structs, Classes, and Actors in Swift: Understanding the Differences
In Swift, you have several options for defining data types: structs, classes, and the more recent addition of actors. Each option has its own unique characteristics and use cases, and understanding the differences between them is crucial for writing efficient and effective code. In this post, we'll explore the key distinctions among these three types and when to choose one over the others.
Memory Management
Structs are value types stored on the stack in memory. When you create an instance of a struct, Swift copies the entire data, making structs efficient for small data structures. However, this copying behavior can become inefficient for larger data sets.
Classes and actors, on the other hand, are reference types allocated on the heap in memory. With classes, you can share and efficiently manage larger objects, but you need to be careful to avoid reference leaks.
Actors take this a step further by providing automatic memory management through internal reference counting.
Inheritance
Structs don't directly support inheritance, but they can adopt protocols for shared functionality.
Classes can inherit properties and behavior from other classes, promoting code reuse and specialization.
Actors in Swift do not support inheritance, nor can they be subclassed or inherited from, except for the Actor
protocol itself.
State Mutability
Struct properties are immutable by default, ensuring predictable behavior in concurrent access scenarios. To mutate a struct, you need to use the mutating
keyword in specific methods.
Classes offer more flexibility with both mutable and immutable properties, but require manual synchronization for concurrent access.
Actors have state isolation baked in, allowing safe concurrent access to both mutable and immutable properties without manual synchronization.
Concurrency
Structs are not inherently thread-safe, and data races can occur if accessed concurrently.
Classes require manual synchronization mechanisms like locks to prevent data races in concurrent scenarios.
Actors are built for concurrency, with messages dispatched sequentially within the actor, ensuring thread-safe operation even with mutable state.
Choosing the Right Type
Structs are ideal for small, immutable data like points or simple configurations.
Use structures by default.
Use structures along with protocols to adopt behavior by sharing implementations.
Apple pushes for structs over classes because the additional capabilities that classes support come at the cost of increased complexity. As a general guideline, prefer structures because they’re easier to reason about.
Classes are preferred for complex objects with inheritance, mutable state, and reference relationships.
Use classes when they’re appropriate or necessary.
Use classes when you need Objective-C interoperability.
Use classes when you need to control the identity of the data you’re modelling.
Actors are essential for managing shared state in concurrent applications where thread safety is paramount.
In Summary
Structs are value types for immutable data, passed by value, and don't have deinitializers.
Classes are reference types for complex objects, support inheritance, and have deinitializers for cleanup.
Actors are reference types specifically designed for safe concurrent access to shared mutable state.
Understanding the differences between structs, classes, and actors in Swift is crucial for writing efficient, maintainable, and thread-safe code. Choose the right type based on your requirements for memory management, inheritance, state mutability, and concurrency.
Subscribe to my newsletter
Read articles from Nurul Islam directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Nurul Islam
Nurul Islam
I'm an experienced mobile application developer with over 10 years of expertise in iOS development using Swift, Objective-C, and Flutter. Throughout my career, I've had the opportunity to work for multiple renowned companies where I developed and architected robust mobile applications used by millions of users worldwide. In addition to my extensive iOS experience, I also have experience working with ASP.Net Core, Entity Framework, and LINQ for backend development as well as Machine Learning and Deep Learning using Python and TensorFlow which has allowed me to collaborate closely with different teams to develop different types of products, apps or services.