Swift DISCUSSION

Swift struct or class for my data model: what changes with value versus reference semantics?

Started by vothanhdat Swift struct vs classvalue semanticsreference typescopy on writemutating methods
5 replies 248 views 6 participants
Latest activity · 30 Sep 2026

Swift struct or class for my data model: what changes with value versus reference semantics?

vothanhdat Swift Forum
#1

I am modelling sensor readings and device settings in Swift. When I made Settings a class, changing it in one screen changed it everywhere, which caused a bug. When I made it a struct, a function that was supposed to update the settings had no effect on the caller's copy, and the compiler complained about mutating a let constant.

What exactly differs between the two, and how do I choose for small data types like these?

Community replies 5

Re: Swift struct or class for my data model: what changes with value versus reference semantics?

#2

A struct is a value type: assignment, passing to a function and capturing all make an independent copy. A class is a reference type: those operations copy a reference, and every holder sees the same object. After var b = a, changing b.gain leaves a.gain alone for a struct and changes it for a class.

Both of your surprises follow from that. The class version was shared state that several screens edited; the struct version handed the function its own copy, so the caller's value never changed.

Re: Swift struct or class for my data model: what changes with value versus reference semantics?

#3

For a function that must change a struct, either return the new value, settings = adjusted(settings), or take it inout: func adjust(_ s: inout Settings) called as adjust(&settings). Methods that modify the struct's own properties must be marked mutating.

The let complaint is also part of value semantics: a struct stored in a let constant is entirely immutable, including its var properties. A class instance in a let can still have its var properties changed, because the constant is only the reference.

Re: Swift struct or class for my data model: what changes with value versus reference semantics?

#4

Feature differences: only classes have inheritance, deinit, and identity (the === operator asks whether two references are the same object). Structs get a memberwise initialiser for free, and the compiler can synthesise Equatable and Hashable for a struct whose properties already conform, just by declaring the conformance; for a class you write those yourself.

Because each copy of a struct is independent, passing structs between threads or tasks does not create shared mutable state, which removes a whole class of data races.

Re: Swift struct or class for my data model: what changes with value versus reference semantics?

#5

On cost: a struct is stored inline with no reference counting of its own. struct Reading { var time: Double; var value: Double } has MemoryLayout<Reading>.size of 16 bytes, and an array of 1,000 of them is one 16 kB buffer, while an array of class instances is 1,000 references to 1,000 separate heap objects.

Copying a struct is cheap when it is small. The standard collections, Array, Dictionary, Set and String, are structs that use copy-on-write: a copy shares the buffer until one side mutates. Your own struct gets that benefit for the collections it contains, but a struct with many large stored fields is copied field by field.

Re: Swift struct or class for my data model: what changes with value versus reference semantics?

#6

One mixed case to watch: a struct that contains a class reference. Copying the struct copies the reference, so both copies share that inner object and the type no longer behaves like a value. Keep value types made of value types where you can.

For choosing: start with a struct for plain data such as readings, settings, messages and coordinates. Use a class when there is one real thing with identity and a lifetime, such as a connection, a device manager or a cache, or when an Objective-C framework requires subclassing. If several screens must see the same settings, keep a single owner object that holds the Settings struct and publishes changes, rather than making the data itself a class.

TEP COMMUNITY