# Variables & Properties
# Creating a Variable
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 (opens new window)
var π: Double = 3.14159
var 🍎🍏: String = "Apples"
# Property Observers
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 beforemyProperty
is set. The new value is available asnewValue
, and the old value is still available asmyProperty
.didSet
is called aftermyProperty
is set. The old value is available asoldValue
, and the new value is now available asmyProperty
.
Note: didSet
and willSet
will not be called in the following cases:
Assigning an initial value
Modifying the variable within its own
didSet
orwillSet
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)
anddidSet(newValue)
are entirely legal, but will considerably confuse readers of your code.
# Lazy Stored Properties
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
Properties can be added to a class (opens new window) or struct (opens new window) (technically enums (opens new window) 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
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
Local variables are defined within a function, method, or closure:
func printSomething() {
let localString = "I'm local!"
print(localString)
}
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!"
print(globalString)
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
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 (opens new window).
# Remarks
Properties: Associated with a type
Variables: Not associated with a type
See the Swift Programming Language iBook (opens new window) for more information.