marek.piasecki.staff.iiar.pwr.wroc.plmarek.piasecki.staff.iiar.pwr.wroc.pl/dydaktyka/mc/L06/TheSwift... ·...
Transcript of marek.piasecki.staff.iiar.pwr.wroc.plmarek.piasecki.staff.iiar.pwr.wroc.pl/dydaktyka/mc/L06/TheSwift... ·...
-
WelcometoSwift
-
AboutSwift
SwiftisanewprogramminglanguageforiOS,OSX,watchOS,andtvOSappsthatbuildsonthebestofCandObjective-C,withouttheconstraintsofCcompatibility.Swiftadoptssafeprogrammingpatternsandaddsmodernfeaturestomakeprogrammingeasier,moreflexible,andmorefun.Swift’scleanslate,backedbythematureandmuch-lovedCocoaandCocoaTouchframeworks,isanopportunitytoreimaginehowsoftwaredevelopmentworks.
Swifthasbeenyearsinthemaking.ApplelaidthefoundationforSwiftbyadvancingourexistingcompiler,debugger,andframeworkinfrastructure.WesimplifiedmemorymanagementwithAutomaticReferenceCounting(ARC).Ourframeworkstack,builtonthesolidbaseofFoundationandCocoa,hasbeenmodernizedandstandardizedthroughout.Objective-Citselfhasevolvedtosupportblocks,collectionliterals,andmodules,enablingframeworkadoptionofmodernlanguagetechnologieswithoutdisruption.Thankstothisgroundwork,wecannowintroduceanewlanguageforthefutureofApplesoftwaredevelopment.
SwiftfeelsfamiliartoObjective-Cdevelopers.ItadoptsthereadabilityofObjective-C’snamedparametersandthepowerofObjective-C’sdynamicobjectmodel.ItprovidesseamlessaccesstoexistingCocoaframeworksandmix-and-matchinteroperabilitywithObjective-Ccode.Buildingfromthiscommonground,Swiftintroducesmanynewfeaturesandunifiestheproceduralandobject-orientedportionsofthelanguage.
Swiftisfriendlytonewprogrammers.Itisthefirstindustrial-qualitysystemsprogramminglanguagethatisasexpressiveandenjoyableasascriptinglanguage.Itsupportsplaygrounds,aninnovativefeaturethatallowsprogrammerstoexperimentwithSwiftcodeandseetheresultsimmediately,withouttheoverheadofbuildingandrunninganapp.
SwiftcombinesthebestinmodernlanguagethinkingwithwisdomfromthewiderAppleengineeringculture.Thecompilerisoptimizedforperformance,andthelanguageisoptimizedfordevelopment,withoutcompromisingoneither.It’sdesignedtoscalefrom“hello,world”toanentireoperatingsystem.AllthismakesSwiftasoundfutureinvestmentfordevelopersandforApple.
SwiftisafantasticwaytowriteiOS,OSX,watchOS,andtvOSapps,andwillcontinuetoevolvewithnewfeaturesandcapabilities.OurgoalsforSwiftareambitious.Wecan’twaittoseewhatyoucreatewithit.
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXPodkreślenie
-
ASwiftTour
Traditionsuggeststhatthefirstprograminanewlanguageshouldprintthewords“Hello,world!”onthescreen.InSwift,thiscanbedoneinasingleline:
print("Hello,world!")
IfyouhavewrittencodeinCorObjective-C,thissyntaxlooksfamiliartoyou—inSwift,thislineofcodeisacompleteprogram.Youdon’tneedtoimportaseparatelibraryforfunctionalitylikeinput/outputorstringhandling.Codewrittenatglobalscopeisusedastheentrypointfortheprogram,soyoudon’tneedamain()function.Youalsodon’tneedtowritesemicolonsattheendofeverystatement.
ThistourgivesyouenoughinformationtostartwritingcodeinSwiftbyshowingyouhowtoaccomplishavarietyofprogrammingtasks.Don’tworryifyoudon’tunderstandsomething—everythingintroducedinthistourisexplainedindetailintherestofthisbook.
NOTE
OnaMac,downloadthePlaygroundanddouble-clickthefiletoopenitinXcode:https://developer.apple.com/go/?id=swift-tour
SimpleValues
Uselettomakeaconstantandvartomakeavariable.Thevalueofaconstantdoesn’tneedtobeknownatcompiletime,butyoumustassignitavalueexactlyonce.Thismeansyoucanuseconstantstonameavaluethatyoudetermineoncebutuseinmanyplaces.
1 varmyVariable=42
2 myVariable=50
3 letmyConstant=42
Aconstantorvariablemusthavethesametypeasthevalueyouwanttoassigntoit.However,youdon’talwayshavetowritethetypeexplicitly.Providingavaluewhenyoucreateaconstantorvariableletsthecompilerinferitstype.Intheexampleabove,thecompilerinfersthatmyVariableisanintegerbecauseitsinitialvalueisaninteger.
https://developer.apple.com/go/?id=swift-tourInstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXProstokąt
InstruktorXProstokąt
-
Iftheinitialvaluedoesn’tprovideenoughinformation(orifthereisnoinitialvalue),specifythetypebywritingitafterthevariable,separatedbyacolon.
1 letimplicitInteger=70
2 letimplicitDouble=70.0
3 letexplicitDouble:Double=70
EXPERIMEN T
CreateaconstantwithanexplicittypeofFloatandavalueof4.
Valuesareneverimplicitlyconvertedtoanothertype.Ifyouneedtoconvertavaluetoadifferenttype,explicitlymakeaninstanceofthedesiredtype.
1 letlabel="Thewidthis"
2 letwidth=94
3 letwidthLabel=label+String(width)
EXPERIMEN T
TryremovingtheconversiontoStringfromthelastline.Whaterrordoyouget?
There’sanevensimplerwaytoincludevaluesinstrings:Writethevalueinparentheses,andwriteabackslash(\)beforetheparentheses.Forexample:
1 letapples=3
2 letoranges=5
3 letappleSummary="Ihave\(apples)apples."
4 letfruitSummary="Ihave\(apples+oranges)piecesoffruit."
EXPERIMEN T
Use\()toincludeafloating-pointcalculationinastringandtoincludesomeone’snameinagreeting.
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXProstokąt
InstruktorXProstokąt
InstruktorXProstokąt
-
Createarraysanddictionariesusingbrackets([]),andaccesstheirelementsbywritingtheindexorkeyinbrackets.Acommaisallowedafterthelastelement.
1 varshoppingList=["catfish","water","tulips","bluepaint"]
2 shoppingList[1]="bottleofwater"
3
4 varoccupations=[
5 "Malcolm":"Captain",
6 "Kaylee":"Mechanic",
7 ]
8 occupations["Jayne"]="PublicRelations"
Tocreateanemptyarrayordictionary,usetheinitializersyntax.
1 letemptyArray=[String]()
2 letemptyDictionary=[String:Float]()
Iftypeinformationcanbeinferred,youcanwriteanemptyarrayas[]andanemptydictionaryas[:]—forexample,whenyousetanewvalueforavariableorpassanargumenttoafunction.
1 shoppingList=[]
2 occupations=[:]
ControlFlow
Useifandswitchtomakeconditionals,andusefor-in,for,while,andrepeat-whiletomakeloops.Parenthesesaroundtheconditionorloopvariableareoptional.Bracesaroundthebodyarerequired.
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXProstokąt
InstruktorXProstokąt
InstruktorXProstokąt
InstruktorXProstokąt
-
1 letindividualScores=[75,43,103,87,12]
2 varteamScore=0
3 forscoreinindividualScores{
4 ifscore>50{
5 teamScore+=3
6 }else{
7 teamScore+=1
8 }
9 }
print(teamScore)
Inanifstatement,theconditionalmustbeaBooleanexpression—thismeansthatcodesuchasifscore{...}isanerror,notanimplicitcomparisontozero.
Youcanuseifandlettogethertoworkwithvaluesthatmightbemissing.Thesevaluesarerepresentedasoptionals.Anoptionalvalueeithercontainsavalueorcontainsniltoindicatethatavalueismissing.Writeaquestionmark(?)afterthetypeofavaluetomarkthevalueasoptional.
1 varoptionalString:String?="Hello"
2 print(optionalString==nil)
3
4 varoptionalName:String?="JohnAppleseed"
5 vargreeting="Hello!"
6 ifletname=optionalName{
7 greeting="Hello,\(name)"
8 }
EXPERIMEN T
ChangeoptionalNametonil.Whatgreetingdoyouget?AddanelseclausethatsetsadifferentgreetingifoptionalNameisnil.
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXProstokąt
InstruktorXProstokąt
-
Iftheoptionalvalueisnil,theconditionalisfalseandthecodeinbracesisskipped.Otherwise,theoptionalvalueisunwrappedandassignedtotheconstantafterlet,whichmakestheunwrappedvalueavailableinsidetheblockofcode.
Anotherwaytohandleoptionalvaluesistoprovideadefaultvalueusingthe??operator.Iftheoptionalvalueismissing,thedefaultvalueisusedinstead.
1 letnickName:String?=nil
2 letfullName:String="JohnAppleseed"
3 letinformalGreeting="Hi\(nickName??fullName)"
Switchessupportanykindofdataandawidevarietyofcomparisonoperations—theyaren’tlimitedtointegersandtestsforequality.
1 letvegetable="redpepper"
2 switchvegetable{
3 case"celery":
4 print("Addsomeraisinsandmakeantsonalog.")
5 case"cucumber","watercress":
6 print("Thatwouldmakeagoodteasandwich.")
7 caseletxwherex.hasSuffix("pepper"):
8 print("Isitaspicy\(x)?")
9 default:
print("Everythingtastesgoodinsoup.")
}
EXPERIMEN T
Tryremovingthedefaultcase.Whaterrordoyouget?
Noticehowletcanbeusedinapatterntoassignthevaluethatmatchedthepatterntoaconstant.
Afterexecutingthecodeinsidetheswitchcasethatmatched,theprogramexitsfromtheswitchstatement.Executiondoesn’tcontinuetothenextcase,sothereisnoneedtoexplicitlybreakoutoftheswitchattheendofeachcase’scode.
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXProstokąt
InstruktorXProstokąt
-
Youusefor-intoiterateoveritemsinadictionarybyprovidingapairofnamestouseforeachkey-valuepair.Dictionariesareanunorderedcollection,sotheirkeysandvaluesareiteratedoverinanarbitraryorder.
1 letinterestingNumbers=[
2 "Prime":[2,3,5,7,11,13],
3 "Fibonacci":[1,1,2,3,5,8],
4 "Square":[1,4,9,16,25],
5 ]
6 varlargest=0
7 for(kind,numbers)ininterestingNumbers{
8 fornumberinnumbers{
9 ifnumber>largest{
largest=number
}
}
}
print(largest)
EXPERIMEN T
Addanothervariabletokeeptrackofwhichkindofnumberwasthelargest,aswellaswhatthatlargestnumberwas.
Usewhiletorepeatablockofcodeuntilaconditionchanges.Theconditionofaloopcanbeattheendinstead,ensuringthattheloopisrunatleastonce.
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXProstokąt
-
1 varn=2
2 whilen<100{
3 n=n*2
4 }
5 print(n)
6
7 varm=2
8 repeat{
9 m=m*2
}whilem<100
print(m)
Youcankeepanindexinaloopbyusing..<tomakearangeofindexes.
1 vartotal=0
2 foriin0..toseparatetheparameternamesandtypesfromthefunction’sreturntype.
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXProstokąt
InstruktorXProstokąt
-
1 funcgreet(name:String,day:String)->String{
2 return"Hello\(name),todayis\(day)."
3 }
4 greet("Bob",day:"Tuesday")
EXPERIMEN T
Removethedayparameter.Addaparametertoincludetoday’slunchspecialinthegreeting.
Useatupletomakeacompoundvalue—forexample,toreturnmultiplevaluesfromafunction.Theelementsofatuplecanbereferredtoeitherbynameorbynumber.
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXPodkreślenie
InstruktorXPodkreślenie
InstruktorXPodkreślenie
InstruktorXPodkreślenie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXProstokąt
-
1 funccalculateStatistics(scores:[Int])->(min:Int,max:Int,sum:Int){
2 varmin=scores[0]
3 varmax=scores[0]
4 varsum=0
5
6 forscoreinscores{
7 ifscore>max{
8 max=score
9 }elseifscore<min{
min=score
}
sum+=score
}
return(min,max,sum)
}
letstatistics=calculateStatistics([5,3,100,3,9])
print(statistics.sum)
print(statistics.2)
Functionscanalsotakeavariablenumberofarguments,collectingthemintoanarray.
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXPodkreślenie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXPodkreślenie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXProstokąt
-
1 funcsumOf(numbers:Int...)->Int{
2 varsum=0
3 fornumberinnumbers{
4 sum+=number
5 }
6 returnsum
7 }
8 sumOf()
9 sumOf(42,597,12)
EXPERIMEN T
Writeafunctionthatcalculatestheaverageofitsarguments.
Functionscanbenested.Nestedfunctionshaveaccesstovariablesthatweredeclaredintheouterfunction.Youcanusenestedfunctionstoorganizethecodeinafunctionthatislongorcomplex.
1 funcreturnFifteen()->Int{
2 vary=10
3 funcadd(){
4 y+=5
5 }
6 add()
7 returny
8 }
9 returnFifteen()
Functionsareafirst-classtype.Thismeansthatafunctioncanreturnanotherfunctionasitsvalue.
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXProstokąt
InstruktorXProstokąt
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXProstokąt
-
1 funcmakeIncrementer()->((Int)->Int){
2 funcaddOne(number:Int)->Int{
3 return1+number
4 }
5 returnaddOne
6 }
7 varincrement=makeIncrementer()
8 increment(7)
Afunctioncantakeanotherfunctionasoneofitsarguments.
1 funchasAnyMatches(list:[Int],condition:(Int)->Bool)->Bool{
2 foriteminlist{
3 ifcondition(item){
4 returntrue
5 }
6 }
7 returnfalse
8 }
9 funclessThanTen(number:Int)->Bool{
returnnumber<10
}
varnumbers=[20,19,7,12]
hasAnyMatches(numbers,condition:lessThanTen)
Functionsareactuallyaspecialcaseofclosures:blocksofcodethatcanbecalledlater.Thecodeinaclosurehasaccesstothingslikevariablesandfunctionsthatwereavailableinthescopewheretheclosurewascreated,eveniftheclosureisinadifferentscopewhenitisexecuted—yousawanexampleofthisalreadywithnestedfunctions.Youcanwriteaclosurewithoutanamebysurroundingcodewithbraces({}).Useintoseparatetheargumentsandreturntypefromthebody.
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXPodkreślenie
InstruktorXPodkreślenie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXPodkreślenie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXProstokąt
InstruktorXProstokąt
InstruktorXProstokąt
-
1 numbers.map({
2 (number:Int)->Intin
3 letresult=3*number
4 returnresult
5 })
EXPERIMEN T
Rewritetheclosuretoreturnzeroforalloddnumbers.
Youhaveseveraloptionsforwritingclosuresmoreconcisely.Whenaclosure’stypeisalreadyknown,suchasthecallbackforadelegate,youcanomitthetypeofitsparameters,itsreturntype,orboth.Singlestatementclosuresimplicitlyreturnthevalueoftheironlystatement.
1 letmappedNumbers=numbers.map({numberin3*number})
2 print(mappedNumbers)
Youcanrefertoparametersbynumberinsteadofbyname—thisapproachisespeciallyusefulinveryshortclosures.Aclosurepassedasthelastargumenttoafunctioncanappearimmediatelyaftertheparentheses.Whenaclosureistheonlyargumenttoafunction,youcanomittheparenthesesentirely.
1 letsortedNumbers=numbers.sort{$0>$1}
2 print(sortedNumbers)
ObjectsandClasses
Useclassfollowedbytheclass’snametocreateaclass.Apropertydeclarationinaclassiswrittenthesamewayasaconstantorvariabledeclaration,exceptthatitisinthecontextofaclass.Likewise,methodandfunctiondeclarationsarewrittenthesameway.
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXProstokąt
-
1 classShape{
2 varnumberOfSides=0
3 funcsimpleDescription()->String{
4 return"Ashapewith\(numberOfSides)sides."
5 }
6 }
EXPERIMEN T
Addaconstantpropertywithlet,andaddanothermethodthattakesanargument.
Createaninstanceofaclassbyputtingparenthesesaftertheclassname.Usedotsyntaxtoaccessthepropertiesandmethodsoftheinstance.
1 varshape=Shape()
2 shape.numberOfSides=7
3 varshapeDescription=shape.simpleDescription()
ThisversionoftheShapeclassismissingsomethingimportant:aninitializertosetuptheclasswhenaninstanceiscreated.Useinittocreateone.
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXPodkreślenie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
-
1 classNamedShape{
2 varnumberOfSides:Int=0
3 varname:String
4
5 init(name:String){
6 self.name=name
7 }
8
9 funcsimpleDescription()->String{
return"Ashapewith\(numberOfSides)sides."
}
}
Noticehowselfisusedtodistinguishthenamepropertyfromthenameargumenttotheinitializer.Theargumentstotheinitializerarepassedlikeafunctioncallwhenyoucreateaninstanceoftheclass.Everypropertyneedsavalueassigned—eitherinitsdeclaration(aswithnumberOfSides)orintheinitializer(aswithname).
Usedeinittocreateadeinitializerifyouneedtoperformsomecleanupbeforetheobjectisdeallocated.
Subclassesincludetheirsuperclassnameaftertheirclassname,separatedbyacolon.Thereisnorequirementforclassestosubclassanystandardrootclass,soyoucanincludeoromitasuperclassasneeded.
Methodsonasubclassthatoverridethesuperclass’simplementationaremarkedwithoverride—overridingamethodbyaccident,withoutoverride,isdetectedbythecompilerasanerror.Thecompileralsodetectsmethodswithoverridethatdon’tactuallyoverrideanymethodinthesuperclass.
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
-
1 classSquare:NamedShape{
2 varsideLength:Double
3
4 init(sideLength:Double,name:String){
5 self.sideLength=sideLength
6 super.init(name:name)
7 numberOfSides=4
8 }
9
funcarea()->Double{
returnsideLength*sideLength
}
overridefuncsimpleDescription()->String{
return"Asquarewithsidesoflength\(sideLength)."
}
}
lettest=Square(sideLength:5.2,name:"mytestsquare")
test.area()
test.simpleDescription()
EXPERIMEN T
MakeanothersubclassofNamedShapecalledCirclethattakesaradiusandanameasargumentstoitsinitializer.Implementanarea()andasimpleDescription()methodontheCircleclass.
Inadditiontosimplepropertiesthatarestored,propertiescanhaveagetterandasetter.
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
-
1 classEquilateralTriangle:NamedShape{
2 varsideLength:Double=0.0
3
4 init(sideLength:Double,name:String){
5 self.sideLength=sideLength
6 super.init(name:name)
7 numberOfSides=3
8 }
9
varperimeter:Double{
get{
return3.0*sideLength
}
set{
sideLength=newValue/3.0
}
}
overridefuncsimpleDescription()->String{
return"Anequilateraltrianglewithsidesoflength\(sideLength)."
}
}
vartriangle=EquilateralTriangle(sideLength:3.1,name:"atriangle")
print(triangle.perimeter)
triangle.perimeter=9.9
print(triangle.sideLength)
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
-
Inthesetterforperimeter,thenewvaluehastheimplicitnamenewValue.Youcanprovideanexplicitnameinparenthesesafterset.
NoticethattheinitializerfortheEquilateralTriangleclasshasthreedifferentsteps:
1. Settingthevalueofpropertiesthatthesubclassdeclares.2. Callingthesuperclass’sinitializer.3. Changingthevalueofpropertiesdefinedbythesuperclass.Anyadditionalsetupworkthatuses
methods,getters,orsetterscanalsobedoneatthispoint.
Ifyoudon’tneedtocomputethepropertybutstillneedtoprovidecodethatisrunbeforeandaftersettinganewvalue,usewillSetanddidSet.Thecodeyouprovideisrunanytimethevaluechangesoutsideofaninitializer.Forexample,theclassbelowensuresthatthesidelengthofitstriangleisalwaysthesameasthesidelengthofitssquare.
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
-
1 classTriangleAndSquare{
2 vartriangle:EquilateralTriangle{
3 willSet{
4 square.sideLength=newValue.sideLength
5 }
6 }
7 varsquare:Square{
8 willSet{
9 triangle.sideLength=newValue.sideLength
}
}
init(size:Double,name:String){
square=Square(sideLength:size,name:name)
triangle=EquilateralTriangle(sideLength:size,name:name)
}
}
vartriangleAndSquare=TriangleAndSquare(size:10,name:"anothertestshape")
print(triangleAndSquare.square.sideLength)
print(triangleAndSquare.triangle.sideLength)
triangleAndSquare.square=Square(sideLength:50,name:"largersquare")
print(triangleAndSquare.triangle.sideLength)
Whenworkingwithoptionalvalues,youcanwrite?beforeoperationslikemethods,properties,andsubscripting.Ifthevaluebeforethe?isnil,everythingafterthe?isignoredandthevalueofthewholeexpressionisnil.Otherwise,theoptionalvalueisunwrapped,andeverythingafterthe?actsontheunwrappedvalue.Inbothcases,thevalueofthewholeexpressionisanoptionalvalue.
1 letoptionalSquare:Square?=Square(sideLength:2.5,name:"optionalsquare")
2 letsideLength=optionalSquare?.sideLength
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
-
EnumerationsandStructures
Useenumtocreateanenumeration.Likeclassesandallothernamedtypes,enumerationscanhavemethodsassociatedwiththem.
1 enumRank:Int{
2 caseAce=1
3 caseTwo,Three,Four,Five,Six,Seven,Eight,Nine,Ten
4 caseJack,Queen,King
5 funcsimpleDescription()->String{
6 switchself{
7 case.Ace:
8 return"ace"
9 case.Jack:
return"jack"
case.Queen:
return"queen"
case.King:
return"king"
default:
returnString(self.rawValue)
}
}
}
letace=Rank.Ace
letaceRawValue=ace.rawValue
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
-
EXPERIMEN T
WriteafunctionthatcomparestwoRankvaluesbycomparingtheirrawvalues.
Bydefault,Swiftassignstherawvaluesstartingatzeroandincrementingbyoneeachtime,butyoucanchangethisbehaviorbyexplicitlyspecifyingvalues.Intheexampleabove,Aceisexplicitlygivenarawvalueof1,andtherestoftherawvaluesareassignedinorder.Youcanalsousestringsorfloating-pointnumbersastherawtypeofanenumeration.UsetherawValuepropertytoaccesstherawvalueofanenumerationcase.
Usetheinit?(rawValue:)initializertomakeaninstanceofanenumerationfromarawvalue.
1 ifletconvertedRank=Rank(rawValue:3){
2 letthreeDescription=convertedRank.simpleDescription()
3 }
Thecasevaluesofanenumerationareactualvalues,notjustanotherwayofwritingtheirrawvalues.Infact,incaseswherethereisn’tameaningfulrawvalue,youdon’thavetoprovideone.
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
-
1 enumSuit{
2 caseSpades,Hearts,Diamonds,Clubs
3 funcsimpleDescription()->String{
4 switchself{
5 case.Spades:
6 return"spades"
7 case.Hearts:
8 return"hearts"
9 case.Diamonds:
return"diamonds"
case.Clubs:
return"clubs"
}
}
}
lethearts=Suit.Hearts
letheartsDescription=hearts.simpleDescription()
EXPERIMEN T
Addacolor()methodtoSuitthatreturns“black”forspadesandclubs,andreturns“red”forheartsanddiamonds.
NoticethetwowaysthattheHeartscaseoftheenumerationisreferredtoabove:Whenassigningavaluetotheheartsconstant,theenumerationcaseSuit.Heartsisreferredtobyitsfullnamebecausetheconstantdoesn’thaveanexplicittypespecified.Insidetheswitch,theenumerationcaseisreferredtobytheabbreviatedform.Heartsbecausethevalueofselfisalreadyknowntobeasuit.Youcanusetheabbreviatedformanytimethevalue’stypeisalreadyknown.
Usestructtocreateastructure.Structuressupportmanyofthesamebehaviorsasclasses,includingmethodsandinitializers.Oneofthemostimportantdifferencesbetweenstructuresandclassesisthatstructuresarealwayscopiedwhentheyarepassedaroundinyourcode,butclassesarepassedbyreference.
InstruktorXWyróżnienie
InstruktorXPodkreślenie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
InstruktorXWyróżnienie
-
1 structCard{
2 varrank:Rank
3 varsuit:Suit
4 funcsimpleDescription()->String{
5 return"The\(rank.simpleDescription())of\(suit.simpleDescription())"
6 }
7 }
8 letthreeOfSpades=Card(rank:.Three,suit:.Spades)
9 letthreeOfSpadesDescription=threeOfSpades.simpleDescription()
EXPERIMEN T
AddamethodtoCardthatcreatesafulldeckofcards,withonecardofeachcombinationofrankandsuit.
Aninstanceofanenumerationcasecanhavevaluesassociatedwiththeinstance.Instancesofthesameenumerationcasecanhavedifferentvaluesassociatedwiththem.Youprovidetheassociatedvalueswhenyoucreatetheinstance.Associatedvaluesandrawvaluesaredifferent:Therawvalueofanenumerationcaseisthesameforallofitsinstances,andyouprovidetherawvaluewhenyoudefinetheenumeration.
Forexample,considerthecaseofrequestingthesunriseandsunsettimefromaserver.Theservereitherrespondswiththeinformationoritrespondswithsomeerrorinformation.
-
1 enumServerResponse{
2 caseResult(String,String)
3 caseFailure(String)
4 }
5
6 letsuccess=ServerResponse.Result("6:00am","8:09pm")
7 letfailure=ServerResponse.Failure("Outofcheese.")
8
9 switchsuccess{
caselet.Result(sunrise,sunset):
print("Sunriseisat\(sunrise)andsunsetisat\(sunset).")
caselet.Failure(message):
print("Failure...\(message)")
}
EXPERIMEN T
AddathirdcasetoServerResponseandtotheswitch.
NoticehowthesunriseandsunsettimesareextractedfromtheServerResponsevalueaspartofmatchingthevalueagainsttheswitchcases.
ProtocolsandExtensions
Useprotocoltodeclareaprotocol.
-
1 protocolExampleProtocol{
2 varsimpleDescription:String{get}
3 mutatingfuncadjust()
4 }
Classes,enumerations,andstructscanalladoptprotocols.
1 classSimpleClass:ExampleProtocol{
2 varsimpleDescription:String="Averysimpleclass."
3 varanotherProperty:Int=69105
4 funcadjust(){
5 simpleDescription+="Now100%adjusted."
6 }
7 }
8 vara=SimpleClass()
9 a.adjust()
letaDescription=a.simpleDescription
structSimpleStructure:ExampleProtocol{
varsimpleDescription:String="Asimplestructure"
mutatingfuncadjust(){
simpleDescription+="(adjusted)"
}
}
varb=SimpleStructure()
b.adjust()
letbDescription=b.simpleDescription
-
EXPERIMEN T
Writeanenumerationthatconformstothisprotocol.
NoticetheuseofthemutatingkeywordinthedeclarationofSimpleStructuretomarkamethodthatmodifiesthestructure.ThedeclarationofSimpleClassdoesn’tneedanyofitsmethodsmarkedasmutatingbecausemethodsonaclasscanalwaysmodifytheclass.
Useextensiontoaddfunctionalitytoanexistingtype,suchasnewmethodsandcomputedproperties.Youcanuseanextensiontoaddprotocolconformancetoatypethatisdeclaredelsewhere,oreventoatypethatyouimportedfromalibraryorframework.
1 extensionInt:ExampleProtocol{
2 varsimpleDescription:String{
3 return"Thenumber\(self)"
4 }
5 mutatingfuncadjust(){
6 self+=42
7 }
8 }
9 print(7.simpleDescription)
EXPERIMEN T
WriteanextensionfortheDoubletypethataddsanabsoluteValueproperty.
Youcanuseaprotocolnamejustlikeanyothernamedtype—forexample,tocreateacollectionofobjectsthathavedifferenttypesbutthatallconformtoasingleprotocol.Whenyouworkwithvalueswhosetypeisaprotocoltype,methodsoutsidetheprotocoldefinitionarenotavailable.
1 letprotocolValue:ExampleProtocol=a
2 print(protocolValue.simpleDescription)
3 //print(protocolValue.anotherProperty)//Uncommenttoseetheerror
-
EventhoughthevariableprotocolValuehasaruntimetypeofSimpleClass,thecompilertreatsitasthegiventypeofExampleProtocol.Thismeansthatyoucan’taccidentallyaccessmethodsorpropertiesthattheclassimplementsinadditiontoitsprotocolconformance.
ErrorHandling
YourepresenterrorsusinganytypethatadoptstheErrorTypeprotocol.
1 enumPrinterError:ErrorType{
2 caseOutOfPaper
3 caseNoToner
4 caseOnFire
5 }
Usethrowtothrowanerrorandthrowstomarkafunctionthatcanthrowanerror.Ifyouthrowanerrorinafunction,thefunctionreturnsimmediatelyandthecodethatcalledthefunctionhandlestheerror.
1 funcsendToPrinter(printerName:String)throws->String{
2 ifprinterName=="NeverHasToner"{
3 throwPrinterError.NoToner
4 }
5 return"Jobsent"
6 }
Thereareseveralwaystohandleerrors.Onewayistousedo-catch.Insidethedoblock,youmarkcodethatcanthrowanerrorbywritingtryinfrontofit.Insidethecatchblock,theerrorisautomaticallygiventhenameerrorunlessyoucangiveitadifferentname.
-
1 do{
2 letprinterResponse=trysendToPrinter("BiSheng")
3 print(printerResponse)
4 }catch{
5 print(error)
6 }
EXPERIMEN T
Changetheprinternameto"NeverHasToner",sothatthesendToPrinter(_:)functionthrowsanerror.
Youcanprovidemultiplecatchblocksthathandlespecificerrors.Youwriteapatternaftercatchjustasyoudoaftercaseinaswitch.
1 do{
2 letprinterResponse=trysendToPrinter("Gutenberg")
3 print(printerResponse)
4 }catchPrinterError.OnFire{
5 print("I'lljustputthisoverhere,withtherestofthefire.")
6 }catchletprinterErrorasPrinterError{
7 print("Printererror:\(printerError).")
8 }catch{
9 print(error)
}
EXPERIMEN T
Addcodetothrowanerrorinsidethedoblock.Whatkindoferrordoyouneedtothrowsothattheerrorishandledbythefirstcatchblock?Whataboutthesecondandthirdblocks?
Anotherwaytohandleerrorsistousetry?toconverttheresulttoanoptional.Ifthefunctionthrows
-
anerror,thespecificerrorisdiscardedandtheresultisnil.Otherwise,theresultisanoptionalcontainingthevaluethatthefunctionreturned.
1 letprinterSuccess=try?sendToPrinter("Mergenthaler")
2 letprinterFailure=try?sendToPrinter("NeverHasToner")
Usedefertowriteablockofcodethatisexecutedafterallothercodeinthefunction,justbeforethefunctionreturns.Thecodeisexecutedregardlessofwhetherthefunctionthrowsanerror.Youcanusedefertowritesetupandcleanupcodenexttoeachother,eventhoughtheyneedtobeexecutedatdifferenttimes.
1 varfridgeIsOpen=false
2 letfridgeContent=["milk","eggs","leftovers"]
3
4 funcfridgeContains(itemName:String)->Bool{
5 fridgeIsOpen=true
6 defer{
7 fridgeIsOpen=false
8 }
9
letresult=fridgeContent.contains(itemName)
returnresult
}
fridgeContains("banana")
print(fridgeIsOpen)
Generics
Writeanameinsideanglebracketstomakeagenericfunctionortype.
-
1 funcrepeatItem(item:Item,numberOfTimes:Int)->[Item]{
2 varresult=[Item]()
3 for_in0..
-
1 funcanyCommonElements(lhs:T,_rhs:U)-
>Bool{
2 forlhsIteminlhs{
3 forrhsIteminrhs{
4 iflhsItem==rhsItem{
5 returntrue
6 }
7 }
8 }
9 returnfalse
}
anyCommonElements([1,2,3],[3])
EXPERIMEN T
ModifytheanyCommonElements(_:_:)functiontomakeafunctionthatreturnsanarrayoftheelementsthatanytwosequenceshaveincommon.
Writingisthesameaswriting.
-
LanguageGuide
-
TheBasics
SwiftisanewprogramminglanguageforiOS,OSX,watchOS,andtvOSappdevelopment.Nonetheless,manypartsofSwiftwillbefamiliarfromyourexperienceofdevelopinginCandObjective-C.
SwiftprovidesitsownversionsofallfundamentalCandObjective-Ctypes,includingIntforintegers,DoubleandFloatforfloating-pointvalues,BoolforBooleanvalues,andStringfortextualdata.Swiftalsoprovidespowerfulversionsofthethreeprimarycollectiontypes,Array,Set,andDictionary,asdescribedinCollectionTypes.
LikeC,Swiftusesvariablestostoreandrefertovaluesbyanidentifyingname.Swiftalsomakesextensiveuseofvariableswhosevaluescannotbechanged.Theseareknownasconstants,andaremuchmorepowerfulthanconstantsinC.ConstantsareusedthroughoutSwifttomakecodesaferandclearerinintentwhenyouworkwithvaluesthatdonotneedtochange.
Inadditiontofamiliartypes,SwiftintroducesadvancedtypesnotfoundinObjective-C,suchastuples.Tuplesenableyoutocreateandpassaroundgroupingsofvalues.Youcanuseatupletoreturnmultiplevaluesfromafunctionasasinglecompoundvalue.
Swiftalsointroducesoptionaltypes,whichhandletheabsenceofavalue.Optionalssayeither“thereisavalue,anditequalsx”or“thereisn’tavalueatall”.UsingoptionalsissimilartousingnilwithpointersinObjective-C,buttheyworkforanytype,notjustclasses.NotonlyareoptionalssaferandmoreexpressivethannilpointersinObjective-C,theyareattheheartofmanyofSwift’smostpowerfulfeatures.
Swiftisatype-safelanguage,whichmeansthelanguagehelpsyoutobeclearaboutthetypesofvaluesyourcodecanworkwith.IfpartofyourcodeexpectsaString,typesafetypreventsyoufrompassingitanIntbymistake.Likewise,typesafetypreventsyoufromaccidentallypassinganoptionalStringtoapieceofcodethatexpectsanonoptionalString.Typesafetyhelpsyoucatchandfixerrorsasearlyaspossibleinthedevelopmentprocess.
ConstantsandVariables
Constantsandvariablesassociateaname(suchasmaximumNumberOfLoginAttemptsorwelcomeMessage)withavalueofaparticulartype(suchasthenumber10orthestring"Hello").Thevalueofaconstantcannotbechangedonceitisset,whereasavariablecanbesettoadifferentvalueinthefuture.
DeclaringConstantsandVariables
-
Constantsandvariablesmustbedeclaredbeforetheyareused.Youdeclareconstantswiththeletkeywordandvariableswiththevarkeyword.Here’sanexampleofhowconstantsandvariablescanbeusedtotrackthenumberofloginattemptsauserhasmade:
1 letmaximumNumberOfLoginAttempts=10
2 varcurrentLoginAttempt=0
Thiscodecanbereadas:
“DeclareanewconstantcalledmaximumNumberOfLoginAttempts,andgiveitavalueof10.Then,declareanewvariablecalledcurrentLoginAttempt,andgiveitaninitialvalueof0.”
Inthisexample,themaximumnumberofallowedloginattemptsisdeclaredasaconstant,becausethemaximumvalueneverchanges.Thecurrentloginattemptcounterisdeclaredasavariable,becausethisvaluemustbeincrementedaftereachfailedloginattempt.
Youcandeclaremultipleconstantsormultiplevariablesonasingleline,separatedbycommas:
varx=0.0,y=0.0,z=0.0
NOTE
Ifastoredvalueinyourcodeisnotgoingtochange,alwaysdeclareitasaconstantwiththeletkeyword.Usevariablesonlyforstoringvaluesthatneedtobeabletochange.
TypeAnnotations
Youcanprovideatypeannotationwhenyoudeclareaconstantorvariable,tobeclearaboutthekindofvaluestheconstantorvariablecanstore.Writeatypeannotationbyplacingacolonaftertheconstantorvariablename,followedbyaspace,followedbythenameofthetypetouse.
ThisexampleprovidesatypeannotationforavariablecalledwelcomeMessage,toindicatethatthevariablecanstoreStringvalues:
varwelcomeMessage:String
Thecoloninthedeclarationmeans“…oftype…,”sothecodeabovecanbereadas:
“DeclareavariablecalledwelcomeMessagethatisoftypeString.”
Thephrase“oftypeString”means“canstoreanyStringvalue.”Thinkofitasmeaning“thetypeofthing”(or“thekindofthing”)thatcanbestored.
-
ThewelcomeMessagevariablecannowbesettoanystringvaluewithouterror:
welcomeMessage="Hello"
Youcandefinemultiplerelatedvariablesofthesametypeonasingleline,separatedbycommas,withasingletypeannotationafterthefinalvariablename:
varred,green,blue:Double
NOTE
Itisrarethatyouneedtowritetypeannotationsinpractice.Ifyouprovideaninitialvalueforaconstantorvariableatthepointthatitisdefined,Swiftcanalmostalwaysinferthetypetobeusedforthatconstantorvariable,asdescribedinTypeSafetyandTypeInference.InthewelcomeMessageexampleabove,noinitialvalueisprovided,andsothetypeofthewelcomeMessagevariableisspecifiedwithatypeannotationratherthanbeinginferredfromaninitialvalue.
NamingConstantsandVariables
Constantandvariablenamescancontainalmostanycharacter,includingUnicodecharacters:
1 letπ=3.14159
2 let你好="你好世界"
3 let ="dogcow"
Constantandvariablenamescannotcontainwhitespacecharacters,mathematicalsymbols,arrows,private-use(orinvalid)Unicodecodepoints,orline-andbox-drawingcharacters.Norcantheybeginwithanumber,althoughnumbersmaybeincludedelsewherewithinthename.
Onceyou’vedeclaredaconstantorvariableofacertaintype,youcan’tredeclareitagainwiththesamename,orchangeittostorevaluesofadifferenttype.Norcanyouchangeaconstantintoavariableoravariableintoaconstant.
NOTE
IfyouneedtogiveaconstantorvariablethesamenameasareservedSwiftkeyword,surroundthekeywordwithbackticks(`)whenusingitasaname.However,avoidusingkeywordsasnamesunlessyouhaveabsolutelynochoice.
Youcanchangethevalueofanexistingvariabletoanothervalueofacompatibletype.Inthis
-
example,thevalueoffriendlyWelcomeischangedfrom"Hello!"to"Bonjour!":
1 varfriendlyWelcome="Hello!"
2 friendlyWelcome="Bonjour!"
3 //friendlyWelcomeisnow"Bonjour!"
Unlikeavariable,thevalueofaconstantcannotbechangedonceitisset.Attemptingtodosoisreportedasanerrorwhenyourcodeiscompiled:
1 letlanguageName="Swift"
2 languageName="Swift++"
3 //thisisacompile-timeerror-languageNamecannotbechanged
PrintingConstantsandVariables
Youcanprintthecurrentvalueofaconstantorvariablewiththeprint(_:separator:terminator:)function:
1 print(friendlyWelcome)
2 //Prints"Bonjour!"
Theprint(_:separator:terminator:)functionisaglobalfunctionthatprintsoneormorevaluestoanappropriateoutput.InXcode,forexample,theprint(_:separator:terminator:)functionprintsitsoutputinXcode’s“console”pane.Theseparatorandterminatorparameterhavedefaultvalues,soyoucanomitthemwhenyoucallthisfunction.Bydefault,thefunctionterminatesthelineitprintsbyaddingalinebreak.Toprintavaluewithoutalinebreakafterit,passanemptystringastheterminator—forexample,print(someValue,terminator:"").Forinformationaboutparameterswithdefaultvalues,seeDefaultParameterValues.
Swiftusesstringinterpolationtoincludethenameofaconstantorvariableasaplaceholderinalongerstring,andtopromptSwifttoreplaceitwiththecurrentvalueofthatconstantorvariable.Wrapthenameinparenthesesandescapeitwithabackslashbeforetheopeningparenthesis:
1 print("ThecurrentvalueoffriendlyWelcomeis\(friendlyWelcome)")
2 //Prints"ThecurrentvalueoffriendlyWelcomeisBonjour!"
-
NOTE
AlloptionsyoucanusewithstringinterpolationaredescribedinStringInterpolation.
Comments
Usecommentstoincludenonexecutabletextinyourcode,asanoteorremindertoyourself.CommentsareignoredbytheSwiftcompilerwhenyourcodeiscompiled.
CommentsinSwiftareverysimilartocommentsinC.Single-linecommentsbeginwithtwoforward-slashes(//):
//thisisacomment
Multilinecommentsstartwithaforward-slashfollowedbyanasterisk(/*)andendwithanasteriskfollowedbyaforward-slash(*/):
1 /*thisisalsoacomment,
2 butwrittenovermultiplelines*/
UnlikemultilinecommentsinC,multilinecommentsinSwiftcanbenestedinsideothermultilinecomments.Youwritenestedcommentsbystartingamultilinecommentblockandthenstartingasecondmultilinecommentwithinthefirstblock.Thesecondblockisthenclosed,followedbythefirstblock:
1 /*thisisthestartofthefirstmultilinecomment
2 /*thisisthesecond,nestedmultilinecomment*/
3 thisistheendofthefirstmultilinecomment*/
Nestedmultilinecommentsenableyoutocommentoutlargeblocksofcodequicklyandeasily,evenifthecodealreadycontainsmultilinecomments.
Semicolons
Unlikemanyotherlanguages,Swiftdoesnotrequireyoutowriteasemicolon(;)aftereachstatementinyourcode,althoughyoucandosoifyouwish.However,semicolonsarerequiredifyouwanttowritemultipleseparatestatementsonasingleline:
-
1 letcat=" ";print(cat)
2 //Prints" "
Integers
Integersarewholenumberswithnofractionalcomponent,suchas42and-23.Integersareeithersigned(positive,zero,ornegative)orunsigned(positiveorzero).
Swiftprovidessignedandunsignedintegersin8,16,32,and64bitforms.TheseintegersfollowanamingconventionsimilartoC,inthatan8-bitunsignedintegerisoftypeUInt8,anda32-bitsignedintegerisoftypeInt32.LikealltypesinSwift,theseintegertypeshavecapitalizednames.
IntegerBounds
Youcanaccesstheminimumandmaximumvaluesofeachintegertypewithitsminandmaxproperties:
1 letminValue=UInt8.min//minValueisequalto0,andisoftypeUInt8
2 letmaxValue=UInt8.max//maxValueisequalto255,andisoftypeUInt8
Thevaluesofthesepropertiesareoftheappropriate-sizednumbertype(suchasUInt8intheexampleabove)andcanthereforebeusedinexpressionsalongsideothervaluesofthesametype.
Int
Inmostcases,youdon’tneedtopickaspecificsizeofintegertouseinyourcode.Swiftprovidesanadditionalintegertype,Int,whichhasthesamesizeasthecurrentplatform’snativewordsize:
Unlessyouneedtoworkwithaspecificsizeofinteger,alwaysuseIntforintegervaluesinyourcode.Thisaidscodeconsistencyandinteroperability.Evenon32-bitplatforms,Intcanstoreanyvaluebetween-2,147,483,648and2,147,483,647,andislargeenoughformanyintegerranges.
Ona32-bitplatform,IntisthesamesizeasInt32.•Ona64-bitplatform,IntisthesamesizeasInt64.•
-
UInt
Swiftalsoprovidesanunsignedintegertype,UInt,whichhasthesamesizeasthecurrentplatform’snativewordsize:
NOTE
UseUIntonlywhenyouspecificallyneedanunsignedintegertypewiththesamesizeastheplatform’snativewordsize.Ifthisisnotthecase,Intispreferred,evenwhenthevaluestobestoredareknowntobenon-negative.AconsistentuseofIntforintegervaluesaidscodeinteroperability,avoidstheneedtoconvertbetweendifferentnumbertypes,andmatchesintegertypeinference,asdescribedinTypeSafetyandTypeInference.
Floating-PointNumbers
Floating-pointnumbersarenumberswithafractionalcomponent,suchas3.14159,0.1,and-273.15.
Floating-pointtypescanrepresentamuchwiderrangeofvaluesthanintegertypes,andcanstorenumbersthataremuchlargerorsmallerthancanbestoredinanInt.Swiftprovidestwosignedfloating-pointnumbertypes:
NOTE
Doublehasaprecisionofatleast15decimaldigits,whereastheprecisionofFloatcanbeaslittleas6decimaldigits.Theappropriatefloating-pointtypetousedependsonthenatureandrangeofvaluesyouneedtoworkwithinyourcode.Insituationswhereeithertypewouldbeappropriate,Doubleispreferred.
TypeSafetyandTypeInference
Swiftisatype-safelanguage.Atypesafelanguageencouragesyoutobeclearaboutthetypesofvaluesyourcodecanworkwith.IfpartofyourcodeexpectsaString,youcan’tpassitanIntbymistake.
Ona32-bitplatform,UIntisthesamesizeasUInt32.•Ona64-bitplatform,UIntisthesamesizeasUInt64.•
Doublerepresentsa64-bitfloating-pointnumber.•Floatrepresentsa32-bitfloating-pointnumber.•
-
BecauseSwiftistypesafe,itperformstypecheckswhencompilingyourcodeandflagsanymismatchedtypesaserrors.Thisenablesyoutocatchandfixerrorsasearlyaspossibleinthedevelopmentprocess.
Type-checkinghelpsyouavoiderrorswhenyou’reworkingwithdifferenttypesofvalues.However,thisdoesn’tmeanthatyouhavetospecifythetypeofeveryconstantandvariablethatyoudeclare.Ifyoudon’tspecifythetypeofvalueyouneed,Swiftusestypeinferencetoworkouttheappropriatetype.Typeinferenceenablesacompilertodeducethetypeofaparticularexpressionautomaticallywhenitcompilesyourcode,simplybyexaminingthevaluesyouprovide.
Becauseoftypeinference,SwiftrequiresfarfewertypedeclarationsthanlanguagessuchasCorObjective-C.Constantsandvariablesarestillexplicitlytyped,butmuchoftheworkofspecifyingtheirtypeisdoneforyou.
Typeinferenceisparticularlyusefulwhenyoudeclareaconstantorvariablewithaninitialvalue.Thisisoftendonebyassigningaliteralvalue(orliteral)totheconstantorvariableatthepointthatyoudeclareit.(Aliteralvalueisavaluethatappearsdirectlyinyoursourcecode,suchas42and3.14159intheexamplesbelow.)
Forexample,ifyouassignaliteralvalueof42toanewconstantwithoutsayingwhattypeitis,SwiftinfersthatyouwanttheconstanttobeanInt,becauseyouhaveinitializeditwithanumberthatlookslikeaninteger:
1 letmeaningOfLife=42
2 //meaningOfLifeisinferredtobeoftypeInt
Likewise,ifyoudon’tspecifyatypeforafloating-pointliteral,SwiftinfersthatyouwanttocreateaDouble:
1 letpi=3.14159
2 //piisinferredtobeoftypeDouble
SwiftalwayschoosesDouble(ratherthanFloat)wheninferringthetypeoffloating-pointnumbers.
Ifyoucombineintegerandfloating-pointliteralsinanexpression,atypeofDoublewillbeinferredfromthecontext:
1 letanotherPi=3+0.14159
2 //anotherPiisalsoinferredtobeoftypeDouble
Theliteralvalueof3hasnoexplicittypeinandofitself,andsoanappropriateoutputtypeofDoubleisinferredfromthepresenceofafloating-pointliteralaspartoftheaddition.
-
NumericLiterals
Integerliteralscanbewrittenas:
Alloftheseintegerliteralshaveadecimalvalueof17:
1 letdecimalInteger=17
2 letbinaryInteger=0b10001//17inbinarynotation
3 letoctalInteger=0o21//17inoctalnotation
4 lethexadecimalInteger=0x11//17inhexadecimalnotation
Floating-pointliteralscanbedecimal(withnoprefix),orhexadecimal(witha0xprefix).Theymustalwayshaveanumber(orhexadecimalnumber)onbothsidesofthedecimalpoint.Decimalfloatscanalsohaveanoptionalexponent,indicatedbyanuppercaseorlowercasee;hexadecimalfloatsmusthaveanexponent,indicatedbyanuppercaseorlowercasep.
Fordecimalnumberswithanexponentofexp,thebasenumberismultipliedby10exp:
Forhexadecimalnumberswithanexponentofexp,thebasenumberismultipliedby2exp:
Allofthesefloating-pointliteralshaveadecimalvalueof12.1875:
Adecimalnumber,withnoprefix•Abinarynumber,witha0bprefix•Anoctalnumber,witha0oprefix•Ahexadecimalnumber,witha0xprefix•
1.25e2means1.25x102,or125.0.•
1.25e-2means1.25x10-2,or0.0125.•
0xFp2means15x22,or60.0.•
0xFp-2means15x2-2,or3.75.•
-
1 letdecimalDouble=12.1875
2 letexponentDouble=1.21875e1
3 lethexadecimalDouble=0xC.3p0
Numericliteralscancontainextraformattingtomakethemeasiertoread.Bothintegersandfloatscanbepaddedwithextrazerosandcancontainunderscorestohelpwithreadability.Neithertypeofformattingaffectstheunderlyingvalueoftheliteral:
1 letpaddedDouble=000123.456
2 letoneMillion=1_000_000
3 letjustOverOneMillion=1_000_000.000_000_1
NumericTypeConversion
UsetheInttypeforallgeneral-purposeintegerconstantsandvariablesinyourcode,eveniftheyareknowntobenon-negative.Usingthedefaultintegertypeineverydaysituationsmeansthatintegerconstantsandvariablesareimmediatelyinteroperableinyourcodeandwillmatchtheinferredtypeforintegerliteralvalues.
Useotherintegertypesonlywhentheyarespecificallyneededforthetaskathand,becauseofexplicitly-sizeddatafromanexternalsource,orforperformance,memoryusage,orothernecessaryoptimization.Usingexplicitly-sizedtypesinthesesituationshelpstocatchanyaccidentalvalueoverflowsandimplicitlydocumentsthenatureofthedatabeingused.
IntegerConversion
Therangeofnumbersthatcanbestoredinanintegerconstantorvariableisdifferentforeachnumerictype.AnInt8constantorvariablecanstorenumbersbetween-128and127,whereasaUInt8constantorvariablecanstorenumbersbetween0and255.Anumberthatwillnotfitintoaconstantorvariableofasizedintegertypeisreportedasanerrorwhenyourcodeiscompiled:
-
1 letcannotBeNegative:UInt8=-1
2 //UInt8cannotstorenegativenumbers,andsothiswillreportanerror
3 lettooBig:Int8=Int8.max+1
4 //Int8cannotstoreanumberlargerthanitsmaximumvalue,
5 //andsothiswillalsoreportanerror
Becauseeachnumerictypecanstoreadifferentrangeofvalues,youmustoptintonumerictypeconversiononacase-by-casebasis.Thisopt-inapproachpreventshiddenconversionerrorsandhelpsmaketypeconversionintentionsexplicitinyourcode.
Toconvertonespecificnumbertypetoanother,youinitializeanewnumberofthedesiredtypewiththeexistingvalue.Intheexamplebelow,theconstanttwoThousandisoftypeUInt16,whereastheconstantoneisoftypeUInt8.Theycannotbeaddedtogetherdirectly,becausetheyarenotofthesametype.Instead,thisexamplecallsUInt16(one)tocreateanewUInt16initializedwiththevalueofone,andusesthisvalueinplaceoftheoriginal:
1 lettwoThousand:UInt16=2_000
2 letone:UInt8=1
3 lettwoThousandAndOne=twoThousand+UInt16(one)
BecausebothsidesoftheadditionarenowoftypeUInt16,theadditionisallowed.Theoutputconstant(twoThousandAndOne)isinferredtobeoftypeUInt16,becauseitisthesumoftwoUInt16values.
SomeType(ofInitialValue)isthedefaultwaytocalltheinitializerofaSwifttypeandpassinaninitialvalue.Behindthescenes,UInt16hasaninitializerthatacceptsaUInt8value,andsothisinitializerisusedtomakeanewUInt16fromanexistingUInt8.Youcan’tpassinanytypehere,however—ithastobeatypeforwhichUInt16providesaninitializer.Extendingexistingtypestoprovideinitializersthatacceptnewtypes(includingyourowntypedefinitions)iscoveredinExtensions.
IntegerandFloating-PointConversion
Conversionsbetweenintegerandfloating-pointnumerictypesmustbemadeexplicit:
-
1 letthree=3
2 letpointOneFourOneFiveNine=0.14159
3 letpi=Double(three)+pointOneFourOneFiveNine
4 //piequals3.14159,andisinferredtobeoftypeDouble
Here,thevalueoftheconstantthreeisusedtocreateanewvalueoftypeDouble,sothatbothsidesoftheadditionareofthesametype.Withoutthisconversioninplace,theadditionwouldnotbeallowed.
Floating-pointtointegerconversionmustalsobemadeexplicit.AnintegertypecanbeinitializedwithaDoubleorFloatvalue:
1 letintegerPi=Int(pi)
2 //integerPiequals3,andisinferredtobeoftypeInt
Floating-pointvaluesarealwaystruncatedwhenusedtoinitializeanewintegervalueinthisway.Thismeansthat4.75becomes4,and-3.9becomes-3.
NOTE
Therulesforcombiningnumericconstantsandvariablesaredifferentfromtherulesfornumericliterals.Theliteralvalue3canbeaddeddirectlytotheliteralvalue0.14159,becausenumberliteralsdonothaveanexplicittypeinandofthemselves.Theirtypeisinferredonlyatthepointthattheyareevaluatedbythecompiler.
TypeAliases
Typealiasesdefineanalternativenameforanexistingtype.Youdefinetypealiaseswiththetypealiaskeyword.
Typealiasesareusefulwhenyouwanttorefertoanexistingtypebyanamethatiscontextuallymoreappropriate,suchaswhenworkingwithdataofaspecificsizefromanexternalsource:
typealiasAudioSample=UInt16
Onceyoudefineatypealias,youcanusethealiasanywhereyoumightusetheoriginalname:
1 varmaxAmplitudeFound=AudioSample.min
2 //maxAmplitudeFoundisnow0
-
Here,AudioSampleisdefinedasanaliasforUInt16.Becauseitisanalias,thecalltoAudioSample.minactuallycallsUInt16.min,whichprovidesaninitialvalueof0forthemaxAmplitudeFoundvariable.
Booleans
SwifthasabasicBooleantype,calledBool.Booleanvaluesarereferredtoaslogical,becausetheycanonlyeverbetrueorfalse.SwiftprovidestwoBooleanconstantvalues,trueandfalse:
1 letorangesAreOrange=true
2 letturnipsAreDelicious=false
ThetypesoforangesAreOrangeandturnipsAreDelicioushavebeeninferredasBoolfromthefactthattheywereinitializedwithBooleanliteralvalues.AswithIntandDoubleabove,youdon’tneedtodeclareconstantsorvariablesasBoolifyousetthemtotrueorfalseassoonasyoucreatethem.TypeinferencehelpsmakeSwiftcodemoreconciseandreadablewhenitinitializesconstantsorvariableswithothervalueswhosetypeisalreadyknown.
Booleanvaluesareparticularlyusefulwhenyouworkwithconditionalstatementssuchastheifstatement:
1 ifturnipsAreDelicious{
2 print("Mmm,tastyturnips!")
3 }else{
4 print("Eww,turnipsarehorrible.")
5 }
6 //Prints"Eww,turnipsarehorrible."
ConditionalstatementssuchastheifstatementarecoveredinmoredetailinControlFlow.
Swift’stypesafetypreventsnon-BooleanvaluesfrombeingsubstitutedforBool.Thefollowingexamplereportsacompile-timeerror:
1 leti=1
2 ifi{
3 //thisexamplewillnotcompile,andwillreportanerror
4 }
-
However,thealternativeexamplebelowisvalid:
1 leti=1
2 ifi==1{
3 //thisexamplewillcompilesuccessfully
4 }
Theresultofthei==1comparisonisoftypeBool,andsothissecondexamplepassesthetype-check.Comparisonslikei==1arediscussedinBasicOperators.
AswithotherexamplesoftypesafetyinSwift,thisapproachavoidsaccidentalerrorsandensuresthattheintentionofaparticularsectionofcodeisalwaysclear.
Tuples
Tuplesgroupmultiplevaluesintoasinglecompoundvalue.Thevalueswithinatuplecanbeofanytypeanddonothavetobeofthesametypeaseachother.
Inthisexample,(404,"NotFound")isatuplethatdescribesanHTTPstatuscode.AnHTTPstatuscodeisaspecialvaluereturnedbyawebserverwheneveryourequestawebpage.Astatuscodeof404NotFoundisreturnedifyourequestawebpagethatdoesn’texist.
1 lethttp404Error=(404,"NotFound")
2 //http404Errorisoftype(Int,String),andequals(404,"NotFound")
The(404,"NotFound")tuplegroupstogetheranIntandaStringtogivetheHTTPstatuscodetwoseparatevalues:anumberandahuman-readabledescription.Itcanbedescribedas“atupleoftype(Int,String)”.
Youcancreatetuplesfromanypermutationoftypes,andtheycancontainasmanydifferenttypesasyoulike.There’snothingstoppingyoufromhavingatupleoftype(Int,Int,Int),or(String,Bool),orindeedanyotherpermutationyourequire.
Youcandecomposeatuple’scontentsintoseparateconstantsorvariables,whichyouthenaccessasusual:
-
1 let(statusCode,statusMessage)=http404Error
2 print("Thestatuscodeis\(statusCode)")
3 //Prints"Thestatuscodeis404"
4 print("Thestatusmessageis\(statusMessage)")
5 //Prints"ThestatusmessageisNotFound"
Ifyouonlyneedsomeofthetuple’svalues,ignorepartsofthetuplewithanunderscore(_)whenyoudecomposethetuple:
1 let(justTheStatusCode,_)=http404Error
2 print("Thestatuscodeis\(justTheStatusCode)")
3 //Prints"Thestatuscodeis404"
Alternatively,accesstheindividualelementvaluesinatupleusingindexnumbersstartingatzero:
1 print("Thestatuscodeis\(http404Error.0)")
2 //Prints"Thestatuscodeis404"
3 print("Thestatusmessageis\(http404Error.1)")
4 //Prints"ThestatusmessageisNotFound"
Youcannametheindividualelementsinatuplewhenthetupleisdefined:
lethttp200Status=(statusCode:200,description:"OK")
Ifyounametheelementsinatuple,youcanusetheelementnamestoaccessthevaluesofthoseelements:
1 print("Thestatuscodeis\(http200Status.statusCode)")
2 //Prints"Thestatuscodeis200"
3 print("Thestatusmessageis\(http200Status.description)")
4 //Prints"ThestatusmessageisOK"
Tuplesareparticularlyusefulasthereturnvaluesoffunctions.Afunctionthattriestoretrieveawebpagemightreturnthe(Int,String)tupletypetodescribethesuccessorfailureofthepageretrieval.
-
Byreturningatuplewithtwodistinctvalues,eachofadifferenttype,thefunctionprovidesmoreusefulinformationaboutitsoutcomethanifitcouldonlyreturnasinglevalueofasingletype.Formoreinformation,seeFunctionswithMultipleReturnValues.
NOTE
Tuplesareusefulfortemporarygroupsofrelatedvalues.Theyarenotsuitedtothecreationofcomplexdatastructures.Ifyourdatastructureislikelytopersistbeyondatemporaryscope,modelitasaclassorstructure,ratherthanasatuple.Formoreinformation,seeClassesandStructures.
Optionals
Youuseoptionalsinsituationswhereavaluemaybeabsent.Anoptionalsays:
or
NOTE
Theconceptofoptionalsdoesn’texistinCorObjective-C.ThenearestthinginObjective-Cistheabilitytoreturnnilfromamethodthatwouldotherwisereturnanobject,withnilmeaning“theabsenceofavalidobject.”However,thisonlyworksforobjects—itdoesn’tworkforstructures,basicCtypes,orenumerationvalues.Forthesetypes,Objective-Cmethodstypicallyreturnaspecialvalue(suchasNSNotFound)toindicatetheabsenceofavalue.Thisapproachassumesthatthemethod’scallerknowsthereisaspecialvaluetotestagainstandrememberstocheckforit.Swift’soptionalsletyouindicatetheabsenceofavalueforanytypeatall,withouttheneedforspecialconstants.
Here’sanexampleofhowoptionalscanbeusedtocopewiththeabsenceofavalue.Swift’sInttypehasaninitializerwhichtriestoconvertaStringvalueintoanIntvalue.However,noteverystringcanbeconvertedintoaninteger.Thestring"123"canbeconvertedintothenumericvalue123,butthestring"hello,world"doesnothaveanobviousnumericvaluetoconvertto.
TheexamplebelowusestheinitializertotrytoconvertaStringintoanInt:
1 letpossibleNumber="123"
2 letconvertedNumber=Int(possibleNumber)
3 //convertedNumberisinferredtobeoftype"Int?",or"optionalInt"
Thereisavalue,anditequalsx•
Thereisn’tavalueatall•
-
Becausetheinitializermightfail,itreturnsanoptionalInt,ratherthananInt.AnoptionalIntiswrittenasInt?,notInt.Thequestionmarkindicatesthatthevalueitcontainsisoptional,meaningthatitmightcontainsomeIntvalue,oritmightcontainnovalueatall.(Itcan’tcontainanythingelse,suchasaBoolvalueoraStringvalue.It’seitheranInt,orit’snothingatall.)
nil
Yousetanoptionalvariabletoavaluelessstatebyassigningitthespecialvaluenil:
1 varserverResponseCode:Int?=404
2 //serverResponseCodecontainsanactualIntvalueof404
3 serverResponseCode=nil
4 //serverResponseCodenowcontainsnovalue
NOTE
nilcannotbeusedwithnonoptionalconstantsandvariables.Ifaconstantorvariableinyourcodeneedstoworkwiththeabsenceofavalueundercertainconditions,alwaysdeclareitasanoptionalvalueoftheappropriatetype.
Ifyoudefineanoptionalvariablewithoutprovidingadefaultvalue,thevariableisautomaticallysettonilforyou:
1 varsurveyAnswer:String?
2 //surveyAnswerisautomaticallysettonil
NOTE
Swift’snilisnotthesameasnilinObjective-C.InObjective-C,nilisapointertoanonexistentobject.InSwift,nilisnotapointer—itistheabsenceofavalueofacertaintype.Optionalsofanytypecanbesettonil,notjustobjecttypes.
IfStatementsandForcedUnwrapping
Youcanuseanifstatementtofindoutwhetheranoptionalcontainsavaluebycomparingtheoptionalagainstnil.Youperformthiscomparisonwiththe“equalto”operator(==)orthe“notequalto”operator(!=).
-
Ifanoptionalhasavalue,itisconsideredtobe“notequalto”nil:
1 ifconvertedNumber!=nil{
2 print("convertedNumbercontainssomeintegervalue.")
3 }
4 //Prints"convertedNumbercontainssomeintegervalue."
Onceyou’resurethattheoptionaldoescontainavalue,youcanaccessitsunderlyingvaluebyaddinganexclamationmark(!)totheendoftheoptional’sname.Theexclamationmarkeffectivelysays,“Iknowthatthisoptionaldefinitelyhasavalue;pleaseuseit.”Thisisknownasforcedunwrappingoftheoptional’svalue:
1 ifconvertedNumber!=nil{
2 print("convertedNumberhasanintegervalueof\(convertedNumber!).")
3 }
4 //Prints"convertedNumberhasanintegervalueof123."
Formoreontheifstatement,seeControlFlow.
NOTE
Tryingtouse!toaccessanonexistentoptionalvaluetriggersaruntimeerror.Alwaysmakesurethatanoptionalcontainsanon-nilvaluebeforeusing!toforce-unwrapitsvalue.
OptionalBinding
Youuseoptionalbindingtofindoutwhetheranoptionalcontainsavalue,andifso,tomakethatvalueavailableasatemporaryconstantorvariable.Optionalbindingcanbeusedwithifandwhilestatementstocheckforavalueinsideanoptional,andtoextractthatvalueintoaconstantorvariable,aspartofasingleaction.ifandwhilestatementsaredescribedinmoredetailinControlFlow.
Writeanoptionalbindingforanifstatementasfollows:
-
iflet constantName = someOptional {
statements
}
YoucanrewritethepossibleNumberexamplefromtheOptionalssectiontouseoptionalbindingratherthanforcedunwrapping:
1 ifletactualNumber=Int(possibleNumber){
2 print("\"\(possibleNumber)\"hasanintegervalueof\(actualNumber)")
3 }else{
4 print("\"\(possibleNumber)\"couldnotbeconvertedtoaninteger")
5 }
6 //Prints""123"hasanintegervalueof123"
Thiscodecanbereadas:
“IftheoptionalIntreturnedbyInt(possibleNumber)containsavalue,setanewconstantcalledactualNumbertothevaluecontainedintheoptional.”
Iftheconversionissuccessful,theactualNumberconstantbecomesavailableforusewithinthefirstbranchoftheifstatement.Ithasalreadybeeninitializedwiththevaluecontainedwithintheoptional,andsothereisnoneedtousethe!suffixtoaccessitsvalue.Inthisexample,actualNumberissimplyusedtoprinttheresultoftheconversion.
Youcanusebothconstantsandvariableswithoptionalbinding.IfyouwantedtomanipulatethevalueofactualNumberwithinthefirstbranchoftheifstatement,youcouldwriteifvaractualNumberinstead,andthevaluecontainedwithintheoptionalwouldbemadeavailableasavariableratherthanaconstant.
YoucanincludemultipleoptionalbindingsinasingleifstatementanduseawhereclausetocheckforaBooleancondition.Ifanyofthevaluesintheoptionalbindingsarenilorthewhereclauseevaluatestofalse,thewholeoptionalbindingisconsideredunsuccessful.
1 ifletfirstNumber=Int("4"),secondNumber=Int("42")wherefirstNumber<
secondNumber{
2 print("\(firstNumber)<\(secondNumber)")
3 }
4 //Prints"4<42"
-
NOTE
Constantsandvariablescreatedwithoptionalbindinginanifstatement.areavailableonlywithinthebodyoftheifstatement.Incontrast,theconstantsandvariablescreatedwithaguardstatementareavailableinthelinesofcodethatfollowtheguardstatement,asdescribedinEarlyExit,
ImplicitlyUnwrappedOptionals
Asdescribedabove,optionalsindicatethataconstantorvariableisallowedtohave“novalue”.Optionalscanbecheckedwithanifstatementtoseeifavalueexists,andcanbeconditionallyunwrappedwithoptionalbindingtoaccesstheoptional’svalueifitdoesexist.
Sometimesitisclearfromaprogram’sstructurethatanoptionalwillalwayshaveavalue,afterthatvalueisfirstset.Inthesecases,itisusefultoremovetheneedtocheckandunwraptheoptional’svalueeverytimeitisaccessed,becauseitcanbesafelyassumedtohaveavalueallofthetime.
Thesekindsofoptionalsaredefinedasimplicitlyunwrappedoptionals.Youwriteanimplicitlyunwrappedoptionalbyplacinganexclamationmark(String!)ratherthanaquestionmark(String?)afterthetypethatyouwanttomakeoptional.
Implicitlyunwrappedoptionalsareusefulwhenanoptional’svalueisconfirmedtoexistimmediatelyaftertheoptionalisfirstdefinedandcandefinitelybeassumedtoexistateverypointthereafter.TheprimaryuseofimplicitlyunwrappedoptionalsinSwiftisduringclassinitialization,asdescribedinUnownedReferencesandImplicitlyUnwrappedOptionalProperties.
Animplicitlyunwrappedoptionalisanormaloptionalbehindthescenes,butcanalsobeusedlikeanonoptionalvalue,withouttheneedtounwraptheoptionalvalueeachtimeitisaccessed.ThefollowingexampleshowsthedifferenceinbehaviorbetweenanoptionalstringandanimplicitlyunwrappedoptionalstringwhenaccessingtheirwrappedvalueasanexplicitString:
1 letpossibleString:String?="Anoptionalstring."
2 letforcedString:String=possibleString!//requiresanexclamationmark
3
4 letassumedString:String!="Animplicitlyunwrappedoptionalstring."
5 letimplicitString:String=assumedString//noneedforanexclamationmark
Youcanthinkofanimplicitlyunwrappedoptionalasgivingpermissionfortheoptionaltobeunwrappedautomaticallywheneveritisused.Ratherthanplacinganexclamationmarkaftertheoptional’snameeachtimeyouuseit,youplaceanexclamationmarkaftertheoptional’stypewhenyoudeclareit.
-
NOTE
Ifanimplicitlyunwrappedoptionalisnilandyoutrytoaccessitswrappedvalue,you’lltriggeraruntimeerror.Theresultisexactlythesameasifyouplaceanexclamationmarkafteranormaloptionalthatdoesnotcontainavalue.
Youcanstilltreatanimplicitlyunwrappedoptionallikeanormaloptional,tocheckifitcontainsavalue:
1 ifassumedString!=nil{
2 print(assumedString)
3 }
4 //Prints"Animplicitlyunwrappedoptionalstring."
Youcanalsouseanimplicitlyunwrappedoptionalwithoptionalbinding,tocheckandunwrapitsvalueinasinglestatement:
1 ifletdefiniteString=assumedString{
2 print(definiteString)
3 }
4 //Prints"Animplicitlyunwrappedoptionalstring."
NOTE
Donotuseanimplicitlyunwrappedoptionalwhenthereisapossibilityofavariablebecomingnilatalaterpoint.Alwaysuseanormaloptionaltypeifyouneedtocheckforanilvalueduringthelifetimeofavariable.
ErrorHandling
Youuseerrorhandlingtorespondtoerrorconditionsyourprogrammayencounterduringexecution.
Incontrasttooptionals,whichcanusethepresenceorabsenceofavaluetocommunicatesuccessorfailureofafunction,errorhandlingallowsyoutodeterminetheunderlyingcauseoffailure,and,ifnecessary,propagatetheerrortoanotherpartofyourprogram.
Whenafunctionencountersanerrorcondition,itthrowsanerror.Thatfunction’scallercanthen
-
catchtheerrorandrespondappropriately.
1 funccanThrowAnError()throws{
2 //thisfunctionmayormaynotthrowanerror
3 }
Afunctionindicatesthatitcanthrowanerrorbyincludingthethrowskeywordinitsdeclaration.Whenyoucallafunctionthatcanthrowanerror,youprependthetrykeywordtotheexpression.
Swiftautomaticallypropagateserrorsoutoftheircurrentscopeuntiltheyarehandledbyacatchclause.
1 do{
2 trycanThrowAnError()
3 //noerrorwasthrown
4 }catch{
5 //anerrorwasthrown
6 }
Adostatementcreatesanewcontainingscope,whichallowserrorstobepropagatedtooneormorecatchclauses.
Here’sanexampleofhowerrorhandlingcanbeusedtorespondtodifferenterrorconditions:
-
1 funcmakeASandwich()throws{
2 //...
3 }
4
5 do{
6 trymakeASandwich()
7 eatASandwich()
8 }catchError.OutOfCleanDishes{
9 washDishes()
}catchError.MissingIngredients(letingredients){
buyGroceries(ingredients)
}
Inthisexample,themakeASandwich()functionwillthrowanerrorifnocleandishesareavailableorifanyingredientsaremissing.BecausemakeASandwich()canthrowanerror,thefunctioncalliswrappedinatryexpression.Bywrappingthefunctioncallinadostatement,anyerrorsthatarethrownwillbepropagatedtotheprovidedcatchclauses.
Ifnoerroristhrown,theeatASandwich()functioniscalled.IfanerroristhrownanditmatchestheError.OutOfCleanDishescase,thenthewashDishes()functionwillbecalled.IfanerroristhrownanditmatchestheError.MissingIngredientscase,thenthebuyGroceries(_:)functioniscalledwiththeassociated[String]valuecapturedbythecatchpattern.
Throwing,catching,andpropagatingerrorsiscoveredingreaterdetailinErrorHandling.
Assertions
Insomecases,itissimplynotpossibleforyourcodetocontinueexecutionifaparticularconditionisnotsatisfied.Inthesesituations,youcantriggeranassertioninyourcodetoendcodeexecutionandtoprovideanopportunitytodebugthecauseoftheabsentorinvalidvalue.
DebuggingwithAssertions
AnassertionisaruntimecheckthataBooleanconditiondefinitelyevaluatestotrue.Literallyput,an
-
assertion“asserts”thataconditionistrue.Youuseanassertiontomakesurethatanessentialconditionissatisfiedbeforeexecutinganyfurthercode.Iftheconditionevaluatestotrue,codeexecutioncontinuesasusual;iftheconditionevaluatestofalse,codeexecutionends,andyourappisterminated.
Ifyourcodetriggersanassertionwhilerunninginadebugenvironment,suchaswhenyoubuildandrunanappinXcode,youcanseeexactlywheretheinvalidstateoccurredandquerythestateofyourappatthetimethattheassertionwastriggered.Anassertionalsoletsyouprovideasuitabledebugmessageastothenatureoftheassert.
YouwriteanassertionbycallingtheSwiftstandardlibraryglobalassert(_:_:file:line:)function.Youpassthisfunctionanexpressionthatevaluatestotrueorfalseandamessagethatshouldbedisplayediftheresultoftheconditionisfalse:
1 letage=-3
2 assert(age>=0,"Aperson'sagecannotbelessthanzero")
3 //thiscausestheassertiontotrigger,becauseageisnot>=0
Inthisexample,codeexecutionwillcontinueonlyifage>=0evaluatestotrue,thatis,ifthevalueofageisnon-negative.Ifthevalueofageisnegative,asinthecodeabove,thenage>=0evaluatestofalse,andtheassertionistriggered,terminatingtheapplication.
Theassertionmessagecanbeomittedifdesired,asinthefollowingexample:
assert(age>=0)
NOTE
Assertionsaredisabledwhenyourcodeiscompiledwithoptimizations,suchaswhenbuildingwithanapptarget’sdefaultReleaseconfigurationinXcode.
WhentoUseAssertions
Useanassertionwheneveraconditionhasthepotentialtobefalse,butmustdefinitelybetrueinorderforyourcodetocontinueexecution.Suitablescenariosforanassertioncheckinclude:
Anintegersubscriptindexispassedtoacustomsubscriptimplementation,butthesubscriptindexvaluecouldbetoolowortoohigh.
•
Avalueispassedtoafunction,butaninvalidvaluemeansthatthefunctioncannotfulfillitstask.
•
-
SeealsoSubscriptsandFunctions.
NOTE
Assertionscauseyourapptoterminateandarenotasubstitutefordesigningyourcodeinsuchawaythatinvalidconditionsareunlikelytoarise.Nonetheless,insituationswhereinvalidconditionsarepossible,anassertionisaneffectivewaytoensurethatsuchconditionsarehighlightedandnoticedduringdevelopment,beforeyourappispublished.
Anoptionalvalueiscurrentlynil,butanon-nilvalueisessentialforsubsequentcodetoexecutesuccessfully.
•
-
BasicOperators
Anoperatorisaspecialsymbolorphrasethatyouusetocheck,change,orcombinevalues.Forexample,theadditionoperator(+)addstwonumbers,asinleti=1+2,andthelogicalANDoperator(&&)combinestwoBooleanvalues,asinifenteredDoorCode&&passedRetinaScan.
SwiftsupportsmoststandardCoperatorsandimprovesseveralcapabilitiestoeliminatecommoncodingerrors.Theassignmentoperator(=)doesnotreturnavalue,topreventitfrombeingmistakenlyusedwhentheequaltooperator(==)isintended.Arithmeticoperators(+,-,*,/,%andsoforth)detectanddisallowvalueoverflow,toavoidunexpectedresultswhenworkingwithnumbersthatbecomelargerorsmallerthantheallowedvaluerangeofthetypethatstoresthem.YoucanoptintovalueoverflowbehaviorbyusingSwift’soverflowoperators,asdescribedinOverflowOperators.
UnlikeC,Swiftletsyouperformremainder(%)calculationsonfloating-pointnumbers.Swiftalsoprovidestworangeoperators(a..
-
Theassignmentoperator(a=b)initializesorupdatesthevalueofawiththevalueofb:
1 letb=10
2 vara=5
3 a=b
4 //aisnowequalto10
Iftherightsideoftheassignmentisatuplewithmultiplevalues,itselementscanbedecomposedintomultipleconstantsorvariablesatonce:
1 let(x,y)=(1,2)
2 //xisequalto1,andyisequalto2
UnliketheassignmentoperatorinCandObjective-C,theassignmentoperatorinSwiftdoesnotitselfreturnavalue.Thefollowingstatementisnotvalid:
1 ifx=y{
2 //thisisnotvalid,becausex=ydoesnotreturnavalue
3 }
Thisfeaturepreventstheassignmentoperator(=)frombeingusedbyaccidentwhentheequaltooperator(==)isactuallyintended.Bymakingifx=yinvalid,Swifthelpsyoutoavoidthesekindsoferrorsinyourcode.
ArithmeticOperators
Swiftsupportsthefourstandardarithmeticoperatorsforallnumbertypes:
Addition(+)•Subtraction(-)•Multiplication(*)•Division(/)•
-
1 1+2//equals3
2 5-3//equals2
3 2*3//equals6
4 10.0/2.5//equals4.0
UnlikethearithmeticoperatorsinCandObjective-C,theSwiftarithmeticoperatorsdonotallowvaluestooverflowbydefault.YoucanoptintovalueoverflowbehaviorbyusingSwift’soverflowoperators(suchasa&+b).SeeOverflowOperators.
TheadditionoperatorisalsosupportedforStringconcatenation:
"hello,"+"world"//equals"hello,world"
RemainderOperator
Theremainderoperator(a%b)worksouthowmanymultiplesofbwillfitinsideaandreturnsthevaluethatisleftover(knownastheremainder).
NOTE
Theremainderoperator(%)isalsoknownasamodulooperatorinotherlanguages.However,itsbehaviorinSwiftfornegativenumbersmeansthatitis,strictlyspeaking,aremainderratherthanamodulooperation.
Here’showtheremainderoperatorworks.Tocalculate9%4,youfirstworkouthowmany4swillfitinside9:
Youcanfittwo4sinside9,andtheremainderis1(showninorange).
InSwift,thiswouldbewrittenas:
9%4//equals1
Todeterminetheanswerfora%b,the%operatorcalculatesthefollowingequationandreturnsremainderasitsoutput:
-
a=(bxsomemultiplier)+remainder
wheresomemultiplieristhelargestnumberofmultiplesofbthatwillfitinsidea.
Inserting9and4intothisequationyields:
9=(4x2)+1
Thesamemethodisappliedwhencalculatingtheremainderforanegativevalueofa:
-9%4//equals-1
Inserting-9and4intotheequationyields:
-9=(4x-2)+-1
givingaremaindervalueof-1.
Thesignofbisignoredfornegativevaluesofb.Thismeansthata%banda%-balwaysgivethesameanswer.
Floating-PointRemainderCalculations
UnliketheremainderoperatorinCandObjective-C,Swift’sremainderoperatorcanalsooperateonfloating-pointnumbers:
8%2.5//equals0.5
Inthisexample,8dividedby2.5equals3,witharemainderof0.5,sotheremainderoperatorreturnsaDoublevalueof0.5.
UnaryMinusOperator
Thesignofanumericvaluecanbetoggledusingaprefixed-,knownastheunaryminusoperator:
-
1 letthree=3
2 letminusThree=-three//minusThreeequals-3
3 letplusThree=-minusThree//plusThreeequals3,or"minusminusthree"
Theunaryminusoperator(-)isprependeddirectlybeforethevalueitoperateson,withoutanywhitespace.
UnaryPlusOperator
Theunaryplusoperator(+)simplyreturnsthevalueitoperateson,withoutanychange:
1 letminusSix=-6
2 letalsoMinusSix=+minusSix//alsoMinusSixequals-6
Althoughtheunaryplusoperatordoesn’tactuallydoanything,youcanuseittoprovidesymmetryinyourcodeforpositivenumberswhenalsousingtheunaryminusoperatorfornegativenumbers.
CompoundAssignmentOperators
LikeC,Swiftprovidescompoundassignmentoperatorsthatcombineassignment(=)withanotheroperation.Oneexampleistheadditionassignmentoperator(+=):
1 vara=1
2 a+=2
3 //aisnowequalto3
Theexpressiona+=2isshorthandfora=a+2.Effectively,theadditionandtheassignmentarecombinedintooneoperatorthatperformsbothtasksatthesametime.
NOTE
Thecompoundassignmentoperatorsdonotreturnavalue.Forexample,youcannotwriteletb=a+=2.
AcompletelistofcompoundassignmentoperatorscanbefoundinExpressions.
-
ComparisonOperators
SwiftsupportsallstandardCcomparisonoperators:
NOTE
Swiftalsoprovidestwoidentityoperators(===and!==),whichyouusetotestwhethertwoobjectreferencesbothrefertothesameobjectinstance.Formoreinformation,seeClassesandStructures.
EachofthecomparisonoperatorsreturnsaBoolvaluetoindicatewhetherornotthestatementistrue:
1 1==1//truebecause1isequalto1
2 2!=1//truebecause2isnotequalto1
3 2>1//truebecause2isgreaterthan1
4 1<2//truebecause1islessthan2
5 1>=1//truebecause1isgreaterthanorequalto1
6 2b)•Lessthan(a<b)•Greaterthanorequalto(a>=b)•Lessthanorequalto(a
-
1 letname="world"
2 ifname=="world"{
3 print("hello,world")
4 }else{
5 print("I'msorry\(name),butIdon'trecognizeyou")
6 }
7 //prints"hello,world",becausenameisindeedequalto"world"
Formoreontheifstatement,seeControlFlow.
Youcanalsocomparetuplesthathavethesamenumberofvalues,aslongaseachofthevaluesinthetuplecanbecompared.Forexample,bothIntandStringcanbecompared,whichmeanstuplesofthetype(Int,String)canbecompared.Incontrast,Boolcan’tbecompared,whichmeanstuplesthatcontainaBooleanvaluecan’tbecompared.
Tuplesarecomparedfromlefttoright,onevalueatatime,untilthecomparisonfindstwovaluesthataren’tequal.Ifalltheelementsareequal,thenthetuplesthemselvesareequal.Forexample:
1 (1,"zebra")<(2,"apple")//truebecause1islessthan2
2 (3,"apple")<(3,"bird")//truebecause3isequalto3,and"apple"isless
than"bird"
3 (4,"dog")==(4,"dog")//truebecause4isequalto4,and"dog"isequal
to"dog"
NOTE
TheSwiftstandardlibraryincludestuplecomparisonoperatorsfortupleswithlessthansevenelements.Tocomparetupleswithsevenormoreelements,youmustimplementthecomparisonoperatorsyourself.
TernaryConditionalOperator
Theternaryconditionaloperatorisaspecialoperatorwiththreeparts,whichtakestheformquestion?answer1:answer2.Itisashortcutforevaluatingoneoftwoexpressionsbasedonwhetherquestionistrueorfalse.Ifquestionistrue,itevaluatesanswer1andreturnsitsvalue;otherwise,itevaluatesanswer2andreturnsitsvalue.
-
Theternaryconditionaloperatorisshorthandforthecodebelow:
1 ifquestion{
2 answer1
3 }else{
4 answer2
5 }
Here’sanexample,whichcalculatestheheightforatablerow.Therowheightshouldbe50pointstallerthanthecontentheightiftherowhasaheader,and20pointstalleriftherowdoesn’thaveaheader:
1 letcontentHeight=40
2 lethasHeader=true
3 letrowHeight=contentHeight+(hasHeader?50:20)
4 //rowHeightisequalto90
Theprecedingexampleisshorthandforthecodebelow:
1 letcontentHeight=40
2 lethasHeader=true
3 letrowHeight:Int
4 ifhasHeader{
5 rowHeight=contentHeight+50
6 }else{
7 rowHeight=contentHeight+20
8 }
9 //rowHeightisequalto90
Thefirstexample’suseoftheternaryconditionaloperatormeansthatrowHeightcanbesettothecorrectvalueonasinglelineofcode.Thisismoreconcisethanthesecondexample,andremovestheneedforrowHeighttobeavariable,becauseitsvaluedoesnotneedtobemodifiedwithinanifstatement.
-
Theternaryconditionaloperatorprovidesanefficientshorthandfordecidingwhichoftwoexpressionstoconsider.Usetheternaryconditionaloperatorwithcare,however.Itsconcisenesscanleadtohard-to-readcodeifoverused.Avoidcombiningmultipleinstancesoftheternaryconditionaloperatorintoonecompoundstatement.
NilCoalescingOperator
Thenilcoalescingoperator(a??b)unwrapsanoptionalaifitcontainsavalue,orreturnsadefaultvaluebifaisnil.Theexpressionaisalwaysofanoptionaltype.Theexpressionbmustmatchthetypethatisstoredinsidea.
Thenilcoalescingoperatorisshorthandforthecodebelow:
a!=nil?a!:b
Thecodeaboveusestheternaryconditionaloperatorandforcedunwrapping(a!)toaccessthevaluewrappedinsideawhenaisnotnil,andtoreturnbotherwise.Thenilcoalescingoperatorprovidesamoreelegantwaytoencapsulatethisconditionalcheckingandunwrappinginaconciseandreadableform.
NOTE
Ifthevalueofaisnon-nil,thevalueofbisnotevaluated.Thisisknownasshort-circuitevaluation.
Theexamplebelowusesthenilcoalescingoperatortochoosebetweenadefaultcolornameandanoptionaluser-definedcolorname:
1 letdefaultColorName="red"
2 varuserDefinedColorName:String?//defaultstonil
3
4 varcolorNameToUse=userDefinedColorName??defaultColorName
5 //userDefinedColorNameisnil,socolorNameToUseissettothedefaultof"red"
TheuserDefinedColorNamevariableisdefinedasanoptionalString,withadefaultvalueofnil.BecauseuserDefinedColorNameisofanoptionaltype,youcanusethenilcoalescingoperatortoconsideritsvalue.Intheexampleabove,theoperatorisusedtodetermineaninitialvalueforaStringvariablecalledcolorNameToUse.BecauseuserDefinedColorNameisnil,theexpressionuserDefinedColorName??defaultColorNamereturnsthevalueofdefaultColorName,or"red".
-
Ifyouassignanon-nilvaluetouserDefinedColorNameandperformthenilcoalescingoperatorcheckagain,thevaluewrappedinsideuserDefinedColorNameisusedinsteadofthedefault:
1 userDefinedColorName="green"
2 colorNameToUse=userDefinedColorName??defaultColorName
3 //userDefinedColorNameisnotnil,socolorNameToUseissetto"green"
RangeOperators
Swiftincludestworangeoperators,whichareshortcutsforexpressingarangeofvalues.
ClosedRangeOperator
Theclosedrangeoperator(a...b)definesarangethatrunsfromatob,andincludesthevaluesaandb.Thevalueofamustnotbegreaterthanb.
Theclosedrangeoperatorisusefulwheniteratingoverarangeinwhichyouwantallofthevaluestobeused,suchaswithafor-inloop:
1 forindexin1...5{
2 print("\(index)times5is\(index*5)")
3 }
4 //1times5is5
5 //2times5is10
6 //3times5is15
7 //4times5is20
8 //5times5is25
Formoreonfor-inloops,seeControlFlow.
Half-OpenRangeOperator
Thehalf-openrangeoperator(a..
-
saidtobehalf-openbecauseitcontainsitsfirstvalue,butnotitsfinalvalue.Aswiththeclosedrangeoperator,thevalueofamustnotbegreaterthanb.Ifthevalueofaisequaltob,thentheresultingrangewillbeempty.
Half-openrangesareparticularlyusefulwhenyouworkwithzero-basedlistssuchasarrays,whereitisusefultocountupto(butnotincluding)thelengthofthelist:
1 letnames=["Anna","Alex","Brian","Jack"]
2 letcount=names.count
3 foriin0..
-
on,withoutanywhitespace.Itcanbereadas“nota”,asseeninthefollowingexample:
1 letallowedEntry=false
2 if!allowedEntry{
3 print("ACCESSDENIED")
4 }
5 //Prints"ACCESSDENIED"
Thephraseif!allowedEntrycanbereadas“ifnotallowedentry.”Thesubsequentlineisonlyexecutedif“notallowedentry”istrue;thatis,ifallowedEntryisfalse.
Asinthisexample,carefulchoiceofBooleanconstantandvariablenamescanhelptokeepcodereadableandconcise,whileavoidingdoublenegativesorconfusinglogicstatements.
LogicalANDOperator
ThelogicalANDoperator(a&&b)createslogicalexpressionswherebothvaluesmustbetruefortheoverallexpressiontoalsobetrue.
Ifeithervalueisfalse,theoverallexpressionwillalsobefalse.Infact,ifthefirstvalueisfalse,thesecondvaluewon’tevenbeevaluated,becauseitcan’tpossiblymaketheoverallexpressionequatetotrue.Thisisknownasshort-circuitevaluation.
ThisexampleconsiderstwoBoolvaluesandonlyallowsaccessifbothvaluesaretrue:
1 letenteredDoorCode=true
2 letpassedRetinaScan=false
3 ifenteredDoorCode&&passedRetinaScan{
4 print("Welcome!")
5 }else{
6 print("ACCESSDENIED")
7 }
8 //Prints"ACCESSDENIED"
-
LogicalOROperator
ThelogicalORoperator(a||b)isaninfixoperatormadefromtwoadjacentpipecharacters.Youuseittocreatelogicalexpressionsinwhichonlyoneofthetwovalueshastobetruefortheoverallexpressiontobetrue.
LiketheLogicalANDoperatorabove,theLogicalORoperatorusesshort-circuitevaluationtoconsideritsexpressions.IftheleftsideofaLogicalORexpressionistrue,therightsideisnotevaluated,becauseitcannotchangetheoutcomeoftheoverallexpression.
Intheexamplebelow,thefirstBoolvalue(hasDoorKey)isfalse,butthesecondvalue(knowsOverridePassword)istrue.Becauseonevalueistrue,theoverallexpressionalsoevaluatestotrue,andaccessisallowed:
1 lethasDoorKey=false
2 letknowsOverridePassword=true
3 ifhasDoorKey||knowsOverridePassword{
4 print("Welcome!")
5 }else{
6 print("ACCESSDENIED")
7 }
8 //Prints"Welcome!"
CombiningLogicalOperators
Youcancombinemultiplelogicaloperatorstocreatelongercompoundexpressions:
1 ifenteredDoorCode&&passedRetinaScan||hasDoorKey||knowsOverridePassword{
2 print("Welcome!")
3 }else{
4 print("ACCESSDENIED")
5 }
6 //Prints"Welcome!"
-
Thisexampleusesmultiple&&and||operatorstocreatealongercompoundexpression.However,the&&and||operatorsstilloperateononlytwovalues,sothisisactuallythreesmallerexpressionschainedtogether.Theexamplecanbereadas:
Ifwe’veenteredthecorrectdoorcodeandpassedtheretinascan,orifwehaveavaliddoorkey,orifweknowtheemergencyoverridepassword,thenallowaccess.
BasedonthevaluesofenteredDoorCode,passedRetinaScan,andhasDoorKey,thefirsttwosubexpressionsarefalse.However,theemergencyoverridepasswordisknown,sotheoverallcompoundexpressionstillevaluatestotrue.
NOTE
TheSwiftlogicaloperators&&and||areleft-associative,meaningthatcompoundexpressionswithmultiplelogicaloperatorsevaluatetheleftmostsubexpressionfirst.
ExplicitParentheses
Itissometimesusefultoincludeparentheseswhentheyarenotstrictlyneeded,tomaketheintentionofacomplexexpressioneasiertoread.Inthedooraccessexampleabove,itisusefultoaddparenthesesaroundthefirstpartofthecompoundexpressiontomakeitsintentexplicit:
1 if(enteredDoorCode&&passedRetinaScan)||hasDoorKey||knowsOverridePassword{
2 print("Welcome!")
3 }else{
4 print("ACCESSDENIED")
5 }
6 //Prints"Welcome!"
Theparenthesesmakeitclearthatthefirsttwovaluesareconsideredaspartofaseparatepossiblestateintheoveralllogic.Theoutputofthecompoundexpressiondoesn’tcha