Swift Tutorial
Swift Data Types
Swift Control Flow
Swift Functions
Swift Collections
Swift OOPs
Swift Additional Topics
In Swift, properties associate values with a particular class, structure, or enumeration. They allow you to store data within an object and can also provide a way to observe and manipulate that data. Swift has several types of properties:
Stored properties store constant and variable values as part of an instance of a class or structure. Stored properties can be either variable (defined with var
) or constant (defined with let
).
struct Point { var x: Double let y: Double }
In this example, x
is a variable stored property, and y
is a constant stored property.
Instead of storing a value, computed properties provide a getter (and optionally a setter) to compute and return a value. Computed properties can be used in classes, structures, and enumerations.
struct Circle { var radius: Double var area: Double { get { return 3.14 * radius * radius } set(newArea) { radius = sqrt(newArea / 3.14) } } }
Here, area
is a computed property. You can get its value or set a new value (which recalculates the radius).
Property observers observe and respond to changes in property values. They are used with stored properties to execute code before or after a property's value changes. Swift provides two observers: willSet
and didSet
.
class Job { var salary: Double = 0.0 { willSet(newSalary) { print("About to set salary to \(newSalary)") } didSet { print("Salary has changed from \(oldValue) to \(salary)") } } }
While instance properties are associated with an instance, type properties are associated with the type itself (like static variables in some other languages). They can be defined using the static
keyword. For class types, you can also use the class
keyword to allow subclasses to override the superclass's implementation.
struct MathConstants { static let pi = 3.14159265 }
To access a type property, you use the type's name instead of an instance name:
let piValue = MathConstants.pi
A lazy stored property's initial value isn't calculated until the first time it's accessed. You declare a lazy property by adding the lazy
modifier before its declaration. Lazy properties are useful when the initial value for a property is dependent on external factors or if its computation is expensive.
class ExpensiveDataLoader { // This data is not loaded until it's accessed for the first time lazy var expensiveData: String = { // Load and return the data print("Loading data...") return "Expensive Data" }() }
These are computed properties that only have a getter without a setter. They return a value, and that value cannot be set directly.
struct Square { var sideLength: Double var area: Double { return sideLength * sideLength } }
In the Square
example above, area
is a read-only computed property. It computes and returns the area of the square but cannot be set directly.
Properties are fundamental to Swift's approach to data encapsulation and provide a mechanism to establish clear interfaces for accessing and manipulating data within objects.
Stored properties vs computed properties in Swift:
Description: Stored properties store values, while computed properties compute a value on the fly.
// Stored Property struct Rectangle { var width: Double var height: Double } // Computed Property struct Circle { var radius: Double var area: Double { return Double.pi * radius * radius } }
Lazy properties in Swift:
Description: Lazy properties are computed properties that are only calculated when first accessed.
class DataDownloader { lazy var data: Data = { // Download data here return Data() }() }
Swift read-only and read-write properties:
Description: Read-only properties have a getter but no setter, while read-write properties have both.
struct Temperature { var celsius: Double // Read-only property var fahrenheit: Double { return (celsius * 9/5) + 32 } // Read-write property var kelvin: Double { get { return celsius + 273.15 } set { celsius = newValue - 273.15 } } }
Property observers in Swift:
Description: Property observers respond to changes in property values.
class StepCounter { var totalSteps: Int = 0 { willSet(newTotalSteps) { print("About to set totalSteps to \(newTotalSteps)") } didSet { print("Added \(totalSteps - oldValue) steps") } } }
Swift computed properties with getter and setter:
Description: Computed properties can have custom getter and setter.
struct Temperature { private var celsius: Double var fahrenheit: Double { get { return (celsius * 9/5) + 32 } set { celsius = (newValue - 32) * 5/9 } } }
Static properties in Swift:
Description: Static properties belong to the type itself rather than an instance.
struct MathConstants { static let pi = 3.14159 static var version = 1.0 }
Property wrappers in Swift:
Description: Property wrappers add a layer of separation to property values.
@propertyWrapper struct Clamped<Value: Comparable> { private var value: Value private let range: ClosedRange<Value> init(wrappedValue: Value, _ range: ClosedRange<Value>) { self.value = range.clamp(wrappedValue) self.range = range } var wrappedValue: Value { get { return value } set { value = range.clamp(newValue) } } } struct Size { @Clamped(1...10) var width: Int @Clamped(1...10) var height: Int }
Swift instance and type properties:
Description: Instance properties belong to instances, while type properties belong to the type itself.
struct Car { static var totalCars = 0 var brand: String init(brand: String) { self.brand = brand Car.totalCars += 1 } }