structFixedLengthRange{varfirstValue:Intletlength:Int}varrangeOfThreeItems=FixedLengthRange(firstValue:0,length:3)// the range represents integer values 0, 1, and 2rangeOfThreeItems.firstValue=6// the range now represents integer values 6, 7, and 8
Stored Properties of Constant Structure Instances
123456
letrangeOfFourItems=FixedLengthRange(firstValue:0,length:4)// this range represents integer values 0, 1, 2, and 3rangeOfFourItems.firstValue=6// this will report an error, even though firstValue is a variable property// This behavior is due to structures being value types. When an instance of a value type is marked as a constant, so are all of its properties.// The same is not true for classes, which are reference types. If you assign an instance of a reference type to a constant, you can still change that instance’s variable properties.
Lazy Stored Properties
A lazy stored property is a property whose initial value is not calculated until the first time it is used. You indicate a lazy stored property by writing the lazy modifier before its declaration.
1234567891011121314151617181920212223
classDataImporter{/* DataImporter is a class to import data from an external file. The class is assumed to take a non-trivial amount of time to initialize. */varfileName="data.txt"// the DataImporter class would provide data importing functionality here}classDataManager{lazyvarimporter=DataImporter()vardata=[String]()// the DataManager class would provide data management functionality here}letmanager=DataManager()manager.data.append("Some data")manager.data.append("Some more data")// the DataImporter instance for the importer property has not yet been createdprintln(manager.importer.fileName)// the DataImporter instance for the importer property has now been created// prints "data.txt"
Stored Properties and Instance Variables
Computed Properties
123456789101112131415161718192021222324252627
structPoint{varx=0.0,y=0.0}structSize{varwidth=0.0,height=0.0}structRect{varorigin=Point()varsize=Size()varcenter:Point{get{letcenterX=origin.x+(size.width/2)letcenterY=origin.y+(size.height/2)returnPoint(x:centerX,y:centerY)}set(newCenter){origin.x=newCenter.x-(size.width/2)origin.y=newCenter.y-(size.height/2)}}}varsquare=Rect(origin:Point(x:0.0,y:0.0),size:Size(width:10.0,height:10.0))letinitialSquareCenter=square.centersquare.center=Point(x:15.0,y:15.0)println("square.origin is now at (\(square.origin.x), \(square.origin.y))")// prints "square.origin is now at (10.0, 10.0)"
Read-Only Computed Properties
A computed property with a getter but no setter is known as a read-only computed property. A read-only computed property always returns a value, and can be accessed through dot syntax, but cannot be set to a different value.
123456789
structCuboid{varwidth=0.0,height=0.0,depth=0.0varvolume:Double{returnwidth*height*depth}}letfourByFiveByTwo=Cuboid(width:4.0,height:5.0,depth:2.0)println("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")// prints "the volume of fourByFiveByTwo is 40.0"
Property Observers
12345678910111213141516171819202122
classStepCounter{vartotalSteps:Int=0{willSet(newTotalSteps){println("About to set totalSteps to \(newTotalSteps)")}didSet{iftotalSteps>oldValue{println("Added \(totalSteps - oldValue) steps")}}}}letstepCounter=StepCounter()stepCounter.totalSteps=200// About to set totalSteps to 200// Added 200 stepsstepCounter.totalSteps=360// About to set totalSteps to 360// Added 160 stepsstepCounter.totalSteps=896// About to set totalSteps to 896// Added 536 steps
Global and Local Variables
Type Properties (Like C static variables)
1234567891011121314151617
structSomeStructure{staticvarstoredTypeProperty="Some value."staticvarcomputedTypeProperty:Int{// return an Int value here}}enumSomeEnumeration{staticvarstoredTypeProperty="Some value."staticvarcomputedTypeProperty:Int{// return an Int value here}}classSomeClass{classvarcomputedTypeProperty:Int{// return an Int value here}}
println(SomeClass.computedTypeProperty)// prints "42"println(SomeStructure.storedTypeProperty)// prints "Some value."SomeStructure.storedTypeProperty="Another value."println(SomeStructure.storedTypeProperty)// prints "Another value."structAudioChannel{staticletthresholdLevel=10staticvarmaxInputLevelForAllChannels=0varcurrentLevel:Int=0{didSet{ifcurrentLevel>AudioChannel.thresholdLevel{// cap the new audio level to the threshold levelcurrentLevel=AudioChannel.thresholdLevel}ifcurrentLevel>AudioChannel.maxInputLevelForAllChannels{// store this as the new overall maximum input levelAudioChannel.maxInputLevelForAllChannels=currentLevel}}}}varleftChannel=AudioChannel()varrightChannel=AudioChannel()leftChannel.currentLevel=7println(leftChannel.currentLevel)// prints "7"println(AudioChannel.maxInputLevelForAllChannels)// prints "7"rightChannel.currentLevel=11println(rightChannel.currentLevel)// prints "10"println(AudioChannel.maxInputLevelForAllChannels)// prints "10"
Subscripts
Classes, structures, and enumerations can define subscripts, which are shortcuts for accessing the member elements of a collection, list, or sequence. You use subscripts to set and retrieve values by index without needing separate methods for setting and retrieval. For example, you access elements in an Array instance as someArray[index] and elements in a Dictionary instance as someDictionary[key].
Subscript Syntax
12345678910111213
subscript(index:Int)->Int{get{// return an appropriate subscript value here}set(newValue){// perform a suitable setting action here}}// if you want a subscript to be read-onlysubscript(index:Int)->Int{// return an appropriate subscript value here}
A sample, an array to output multiplied index
123456789
structTimesTable{letmultiplier:Intsubscript(index:Int)->Int{returnmultiplier*index}}letthreeTimesTable=TimesTable(multiplier:3)println("six times three is \(threeTimesTable[6])")// prints "six times three is 18"
A sample, a matrix-like structure
123456789101112131415161718192021222324252627
structMatrix{letrows:Int,columns:Intvargrid:[Double]init(rows:Int,columns:Int){self.rows=rowsself.columns=columnsgrid=Array(count:rows*columns,repeatedValue:0.0)}funcindexIsValidForRow(row:Int,column:Int)->Bool{returnrow>=0&&row<rows&&column>=0&&column<columns}subscript(row:Int,column:Int)->Double{get{assert(indexIsValidForRow(row,column:column),"Index out of range")returngrid[(row*columns)+column]}set{assert(indexIsValidForRow(row,column:column),"Index out of range")grid[(row*columns)+column]=newValue}}}// Usagevarmatrix=Matrix(rows:2,columns:2)matrix[0,1]=1.5matrix[1,0]=3.2