Swift Variables & Properties

From WikiOD

Remarks[edit | edit source]

Properties: Associated with a type

Variables: Not associated with a type

See the Swift Programming Language iBook for more information.

Creating a Variable[edit | edit source]

Declare a new variable with var, followed by a name, type, and value:

var num: Int = 10

Variables can have their values changed:

num = 20 // num now equals 20

Unless they're defined with let:

let num: Int = 10 // num cannot change

Swift infers the type of variable, so you don't always have to declare variable type:

let ten = 10 // num is an Int
let pi = 3.14 // pi is a Double
let floatPi: Float = 3.14 // floatPi is a Float

Variable names aren't restricted to letters and numbers - they can also contain most other unicode characters, although there are some restrictions

Constant and variable names cannot contain whitespace characters, mathematical symbols, arrows, private-use (or invalid) Unicode code points, or line- and box-drawing characters. Nor can they begin with a number

Source developer.apple.com

var π: Double = 3.14159
var 🍎🍏: String = "Apples"

Property Observers[edit | edit source]

Property observers respond to changes to a property's value.

var myProperty = 5 {
    willSet {
        print("Will set to \(newValue). It was previously \(myProperty)")
    didSet {
        print("Did set to \(myProperty). It was previously \(oldValue)")
myProperty = 6
// prints: Will set to 6, It was previously 5
// prints: Did set to 6. It was previously 5
  • willSet is called before myProperty is set. The new value is available as newValue, and the old value is still available as myProperty.
  • didSet is called after myProperty is set. The old value is available as oldValue, and the new value is now available as myProperty .

Note: didSet and willSet will not be called in the following cases:

  • Assigning an initial value
  • Modifying the variable within its own didSet or willSet
  • The parameter names for oldValue and newValue of didSet and willSet can also be declared to increase readability:
var myFontSize = 10 {
    willSet(newFontSize) {
        print("Will set font to \(newFontSize), it was \(myFontSize)")
    didSet(oldFontSize) {
        print("Did set font to \(myFontSize), it was \(oldFontSize)")

Caution: While it is supported to declare setter parameter names, one should be cautious not to mix names up:

  • willSet(oldValue) and didSet(newValue) are entirely legal, but will considerably confuse readers of your code.

Lazy Stored Properties[edit | edit source]

Lazy stored properties have values that are not calculated until first accessed. This is useful for memory saving when the variable's calculation is computationally expensive. You declare a lazy property with lazy:

lazy var veryExpensiveVariable = expensiveMethod()

Often it is assigned to a return value of a closure:

lazy var veryExpensiveString = { () -> String in
    var str = expensiveStrFetch()
    str.expensiveManipulation(integer: arc4random_uniform(5))
    return str

Lazy stored properties must be declared with var.

Property Basics[edit | edit source]

Properties can be added to a class or struct (technically enums too, see "Computed Properties" example). These add values that associate with instances of classes/structs:

class Dog {
    var name = ""

In the above case, instances of Dog have a property named name of type String. The property can be accessed and modified on instances of Dog:

let myDog = Dog()
myDog.name = "Doggy" // myDog's name is now "Doggy"

These types of properties are considered stored properties, as they store something on an object and affect its memory.

Computed Properties[edit | edit source]

Different from stored properties, computed properties are built with a getter and a setter, performing necessary code when accessed and set. Computed properties must define a type:

var pi = 3.14

class Circle {
    var radius = 0.0
    var circumference: Double {
        get {
            return pi * radius * 2
        set {
            radius = newValue / pi / 2

let circle = Circle()
circle.radius = 1
print(circle.circumference) // Prints "6.28"
circle.circumference = 14
print(circle.radius) // Prints "2.229..."

A read-only computed property is still declared with a var:

var circumference: Double {
    get {
        return pi * radius * 2

Read*only computed properties can be shortened to exclude get:

var circumference: Double {
    return pi * radius * 2

Local and Global Variables[edit | edit source]

Local variables are defined within a function, method, or closure:

func printSomething() {
    let localString = "I'm local!"

func printSomethingAgain() {
    print(localString) // error

Global variables are defined outside of a function, method, or closure, and are not defined within a type (think outside of all brackets). They can be used anywhere:

let globalString = "I'm global!"

func useGlobalString() {
    print(globalString) // works!

for i in 0..<2 {
    print(globalString) // works!

class GlobalStringUser {
    var computeGlobalString {
        return globalString // works!

Global variables are defined lazily (see "Lazy Properties" example).

Type Properties[edit | edit source]

Type properties are properties on the type itself, not on the instance. They can be both stored or computed properties. You declare a type property with static:

struct Dog {
    static var noise = "Bark!"

print(Dog.noise) // Prints "Bark!"

In a class, you can use the class keyword instead of static to make it overridable. However, you can only apply this on computed properties:

class Animal {
    class var noise: String {
        return "Animal noise!"
class Pig: Animal {
    override class var noise: String {
        return "Oink oink!"

This is used often with the singleton pattern.