Skip to content
tezvyn:
Menu

Swift Properties: Accessors in Disguise

MediumHow cards are made

A Swift property runs code on every read or write. Use stored properties for state, computed properties for derived values, and observers for side effects. The footgun is heavy work in a computed getter, turning innocent dot syntax into a performance trap.

Why it exists

Before Swift, Objective-C separated instance variables from accessor methods. You declared an ivar, then wrote manual getters and setters to enforce invariants, trigger KVO, or compute derived values. That separation leaked implementation details and invited boilerplate. Swift properties collapse storage and access into a single linguistic unit so that the call site always uses dot syntax, while the implementation freely chooses between storage, computation, or observation without breaking the caller.

The mental model

Think of a property as a smart mailbox. To the outside world it looks like a simple slot that holds a letter. Inside, it might be a direct storage bin, a photocopier that generates the letter on demand, or an alarm that rings every time a letter is dropped in. The consumer never knows which mechanism is behind the slot, which is exactly the point: properties decouple the interface of state from the mechanics of state.

How it works

A stored property reserves memory inside the instance and optionally runs willSet and didSet observers when the value changes. A computed property does not reserve storage; instead it executes a getter block to produce a value and an optional setter block to project changes back to other stored properties. A lazy stored property postpones initialization until first access, running a closure once and caching the result. A property wrapper wraps the underlying storage and access logic in a reusable type, letting you annotate declarations with behavior like atomicity, validation, or dependency injection.

When to use it

Use stored properties for the raw data that defines an objects identity or current condition. Use computed properties when a value is derived from other properties and must stay in sync without manual update calls. Use property observers when you need side effects such as logging, cache invalidation, or view layout triggers every time a value mutates. Use property wrappers when the same access logic repeats across many declarations, such as publishing changes to SwiftUI or clamping numeric ranges.

When not to use it

Do not use a computed property for expensive or asynchronous work. If a getter triggers a network request, database query, or long-running algorithm, dot syntax hides the cost and callers will treat it like a free field access. Do not use observers for cross-object coordination; they run synchronously during mutation and can create confusing re-entrancy or cascading updates that are hard to debug. Do not use lazy properties if the initialization closure depends on external state that might change before first access.

One canonical example

A view controller that tracks a download progress bar might store the raw byte count as a stored property. It exposes a computed progress property that divides bytesReceived by totalBytes, keeping the UI label in sync without a manual refresh method. It attaches a didSet observer to progress so that whenever the value crosses one hundred percent it automatically hides the progress view. If many view controllers need the same clamping behavior, a property wrapper can enforce that progress stays between zero and one across the entire codebase.

Interview question

Which scenario best fits the intended use of a Swift computed property?

  • a.Delaying creation of a large image until it is first accessed to improve launch time
  • b.Logging a value change every time a user's score is updated
  • c.Calculating a download percentage from stored byte counts whenever it is readCorrect
  • d.Fetching a user's profile from a server each time the property is accessed
Why?

Computed properties are meant for values derived from other properties, like calculating progress from raw byte counts. Option D is wrong because the card explicitly warns that hiding expensive or asynchronous work such as network requests behind dot syntax creates a performance footgun.

Just read this? Test yourself on what you have been reading.

Put your scrolling time to good use

Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Open roles that interview on swift — each one lists the topics its interview covers.

See open roles