ProgrammingiOS Developer

Explain the differences between value types and reference types in Swift. When should each of them be used?

Pass interviews with Hintsage AI assistant

Answer.

In Swift, there are two main types of data: value types and reference types.

  • Value types. These include structures (struct), enumerations (enum), and basic types like Int, Double, Bool. When passed or assigned, the value is copied, meaning changes to the copy do not affect the original.
  • Reference types. These are classes (class) and associated types. When passed, what is copied is not the object itself but a reference to it, so changes through one reference are visible through others.

When to use:

  • Use value types if you want the data to be independent copies (for example, CGPoint, CGSize, models that should not share state).
  • Reference types are suitable if state sharing between objects is required (for example, managers, controllers, services).

Example:

struct Point { var x: Int var y: Int } class Person { var name: String init(name: String) { self.name = name } } var p1 = Point(x: 0, y: 0) var p2 = p1 p2.x = 10 // p1.x remains 0 var person1 = Person(name: "Alex") var person2 = person1 person2.name = "Sam" // person1.name also becomes "Sam"

Trick question.

What is the difference between let for struct and class? Is an instance of a class created with let completely immutable?

Answer:

For value types (struct), let makes the object and its properties immutable.

For reference types (class), let prevents reassigning the reference, but does not protect the properties of the object. They can be changed unless declared as let within the class.

Example:

class Box { var value: Int init(value: Int) { self.value = value } } let box = Box(value: 10) box.value = 20 // OK! // box = Box(value: 30) // Error: cannot reassign box

Examples of real errors due to ignorance of the nuances of the topic.


Story

In a payment application, the transaction model was defined as a class, even though state should not exist. A bug occurred: when multiple users worked with the transaction list, unpredictable editing of data in different parts of the interface happened. It was decided to switch the models to struct so that each component worked with its own copy.


Story

In the project, user settings were stored in a class, believing that values were copied when passed. When data was changed, one screen unintentionally affected another since both worked with the same object reference.


Story

In the serialization module, the model data was declared as a reference type, which caused any changes to corrupt the state in the cache. After switching to value types, the issue disappeared: data became independent on each operation.