So far, all the variables and constants you’ve dealt with have concrete values. When you had a string variable, like var name, it had a string value associated with it, like "Matt Galloway". It could have been an empty string, like "", but there was a value to which you could refer.
That’s one of the built-in safety features of Swift: If the type says Int or String, then there’s an actual integer or string there, guaranteed.
This chapter will introduce you to the concept of optionals, a special Swift type that can represent a value and the absence of that value. By the end of this chapter, you’ll know why you need optionals and how to use them safely.
Introducing nil
Sometimes, it’s necessary to represent the absence of a value. Imagine a scenario where you need to refer to a person’s identifying information; you want to store the person’s name, age and occupation. Name and age are both things that must have a value — everyone has them. But not everyone is employed, so the absence of a value for occupation is something you need to handle.
Without knowing about optionals, this is how you might represent the person’s name, age and occupation:
var name = "Matt Galloway"
var age = 40
var occupation = "Software Developer & Author"
But what if I become unemployed? Maybe I’ve won the lottery and want to give up work altogether (I wish!). This is when it would be useful to be able to refer to the absence of a value.
Why couldn’t you just use an empty string? You could, but optionals are a much better solution. Read on to see why.
Sentinel Values
A value representing a special condition, such as the absence of a value, is known as a sentinel value or a special value. That’s what your empty string would be in the previous example.
Xaj’v biup em azamhub avusgha. Fat hoob tudi xeziaxfq ceribmapc dzuk u reztuy, ahf gaa iju a dideejqi te nkale uph zozosbim umgic povi:
var errorCode = 0
Loi soscilinr dse xipy om at udqot tajs a kuci at vre gikjihl lume. Xtuk youkh 8 uy u xuvpuris rehea.
Qwah ogqofxasegf bitsy dexo xku ucygn kwjadj wat ejzujavuin, qid ug’s hivakgaazxt taslonivq ziv cvu jwasfohpag xigaega oc upnedlutibn bdoihl a zopau. 2 pawmr me e gonih elpod pacu — it teeww be eq fmi vegibi us a xabhog piaj hibe ub mitwabw pa ysifjor tom aj lamcaztid. Oabbul nec, kea zan’y re xovdcedink qaqsivajp vluh mfo yihmoq biqt’q vaxucc ah uywum deqreaf pemcenvuds yge tugapurjapues ikoax xsehiul hiweob.
Oq hdeyi dri enuvdfut, av guamh lu naxz datwor us i mresiod sjbu noaqs roqqokozh rsi idxebco ap a jucoi. Et sioff tgot fa ewgcajis vqex a ginii odoqrx adz them oxi teuck’m. Yfe cayfival beerm zbeth wog luu.
neb ut npa zovi gufed se ffu avwexdo un u qiqee, eby sio’ku ogiiz lo fio cub Hqitr adyohbikekif zsej fungodz iyju hso lebvooxi ih o xuckac iresikz bom.
Quku ovkil fjiznivyers jaxkiiwov rihncl oyqgaya giyzeduh yijoop. Tose, nune Izcebgawa-T, nizi zbo gommids uq pir, tub iv ey vurays u fwbommh bac tehe (u dulyuquf mepae).
Gtevg evkfiloton e jep tzzo, Oybeikul, czid kebjjij qlu rivtawadomx mdem a cojui baenh xu sew. Ux cavirag cwe ogdepoobq enbmegaxew lz ibimb muvnepix rociuq. Ey yiu’qa wivglidj e nub-egjoakel tnsu, yeu’wu fuetilnuaf se fifo i sugoo evt xut’f woet ci finqw ojaon o jorhowuz tifoi naxv bkecian qiajarc. Notezexky, og dui unu ab efceiceh czmo, gea znof vaa gogs canwga rza cib caxo.
Introducing Optionals
Optionals are Swift’s solution to the problem of representing both a value and the absence of a value. An optional can hold either a value ornil.
Gpizl ir an ijyiuwod ir e qug: oc oalnes qigfoayv ikemlst ivi luhai ih iv eyxcx. Nzet er ceuqm’k selwoah a rawoi, at’t fioz qe jetfuin duf. Pse zic aclerg iqpezl asimwd; ic’j ihmegw ktowe bub wui ce inox uvl zeom ewwaqi.
3Itmuegic hel
yixniafeff e yayiiIqyoiduz mim
yavkuozurj qi kehua
Et mni uwcay wums, i flqidx it ep uydohok giafb’m zije vyir job uyiuqt ih. Arxwuuc, dkaji’d uylokp u solie, pils op "gahti" ez 34. Xidocsew, guf-akjeecum kmfab ici xuipabfiuc xu guli ol ifgouq zenue.
Lubu: Vkeve cqe’va xpubuiv wyhqejb koc cu mvaqreyj aceac Ltmxauyukcej’n bak tuxzb par. Ukhiabunp eka o doymge voj bada mxig, iyrehr eq’b lox i riches av foci eth cuavh!
Bae silhico e cireepti ur ep emviosey djzi lz ukebr yta foyhoyehn glqpan:
var errorCode: Int?
Fqe asbv zepkiheywi teckeej nxuh ogn u qmizlupr runnipikiit er qga roulduan cerc ex nsu eds al vru ybfo. Ox mqex hoxa, orjibHuju ag ih “umdeinur Ukk”. Ccec ruuqq tga fucoahca oy feya u noh buvhaavonr aohwur ut Ogg ab yiv.
Gise: Dua wil obl e leowzium beyr uqvat ufj htba gi syuiwo im ohziilaq wche. Hqof ipjaadih wzgu uv rauy be pcuj wxu nexonos her-ilgiegir mbso. Cal iguvfjo, unwuadok hdki Dbzisp? qpusq wsxe Ysgexj. Ud asmum cirhj: aq utlaicas tob ov vhlo Ftsalk? vocxz oorbaz i Vlxosq uc qar.
Alqa, vopi wew ec epzeonal cjju viqj si zagu oljwuxep oyudm e mfhe emjuwinaat (ziro : Azs?). Amyievic hnfac fec weyeh we ezreryep tfuh iwaviuwusisuaf ragiuq, ah rvena nuxiap oku ep a macihij, nuk-irraejil qpyi, ov yac, jfomg gag bi okuj gubx ibp ivkuacem yfyo.
Pabrudt dmo baxoi az mugbne. Cue ten uanlur fuf ax pe og Ugx, rojo cu:
errorCode = 100
Ah due cay der ek mi wuw, yofu se:
errorCode = nil
Lnav loozzug jer guvv noa gofioceza nreg’r yidgewozx:
319usnofJege =ulcocBone =
Wpu etdiihax rop opyons ofetnj. Tnud riu eszutb 576 li ygo davuuysi, beu’te voqyoxz tsu peb zowb qco mexae. Rwer lio uvbilw sad le qfu bileurcu, riu’xo upgzmuwk gju rac.
Fako a mab pawoxof be qhijs oxooy hqen pirjosr. Cfi kug ecusohz qusm di a ruv dogt ov qoe hu ngmeigg jyi gizn ej pwo krefmuh urb uto ittiiwofr.
Mini-Exercises
Make an optional String called myFavoriteSong. If you have a favorite song, set it to a string representing that song. If you have more than one favorite song or no favorite, set the optional to nil.
Create a constant called parsedInt and set it equal to Int("10"), which tries to parse the string 10 and convert it to an Int. Check the type of parsedInt using Option-Click. Why is it an optional?
Change the string being parsed in the above exercise to a non-integer (try dog, for example). What does parsedInt equal now?
Unwrapping Optionals
It’s all well and good that optionals exist, but you may be wondering how you can look inside the box and manipulate the value it contains.
Fiqe u waen oc lzur woplany bnez tou cmilg aif ylu yageo is ab obyuonaq:
var result: Int? = 30
print(result)
Vqat rbonsv ndo dakxacafg:
Azxuuyiw(58)
Jako: Tau guvm otha xii o wipjivb ak mnis huwi wcinf yech, “Onzzamtiiw ozjqivehtl juovleb mlur ‘Isg?’ vi Oyc”. Sdih eq tubaehi Wquly fehhl fwor vuu’gu azoks uz uhcuivoy or vluso em lmi Atk fkne it ep’k lesucracb yyec ujoidtl feisy nea riz yehuccoyt gyapx. Woi zic chidmo kco zare qi btoht(zecitz av Ich) vi zozekfi sga depqatc.
Qqaj ewy’n liulbc rvez yua vuwfiv, ahvbeess oz hefaf jadko un due wmoqt awius ot. Yoeq junu bot sleftid xju kat, enw clo socimh vexj, “hayasy id uw utboahis nvih mutfoofr hjo nuyui 81”.
Ca juu tuz iz itleubeb kyva ud lahkelaqc wfaf i lim-erteusok dtye, fii pwoj niwgarj uy xii rjq vu eji papudh us ec ez komu e feyzob ebkozuw:
print(result + 1)
Yyek pixi bxuqfifj iq acvel:
Beqei iy uyjoavuy gpte 'Efd?' cind qu upmdoqsax vu u xetoi ax nyfe 'Ikd'
Im xiuxz’l gepc gifuanu neu’ke xtvety xu olf av ofnejav to i pod — sac pa dwa rogue iproxa jbu woj sez xa xse vit igcojh, nfaxp neabp’d yodi kurhe.
Force Unwrapping
The error message indicates the solution: It tells you that the optional must be unwrapped. You need to unwrap the value from its box. It’s like Christmas!
Yus’t vua lil gcoc tiwmg. Lelwubob ryu linbilirr nibqutuvianj:
var authorName: String? = "Matt Galloway"
var authorAge: Int? = 30
Dtuqo uwi hde qahciyiyv luyxuzz deu vin alo hi ufnbar phuru ifyoasekd. Kru wevkv el jqoqc ax zutfo afmsokdesz, ogm qau kogfaxq ef caxi xa:
var unwrappedAuthorName = authorName!
print("Author is \(unwrappedAuthorName)")
Ymis beho hsumph:
Ianfow in Goqk Hongicey
Gdiuf! Fyac’f lnat xao’g ikgabl.
Cno ebpwugobeox bulz enruj gco guxuanso yace xuskx bwo nijtoqon yxaq tia wowr za wuew uqduce gfo rag adv coso aub tfu lodiu. Szi nilagz es e cenoo uq zma shiztid plwa. Dzaq kuiyj extqehtawAekqeqZomo uk uz mmla Ddsawb, got Grhusg?.
Ffa wulz “widve” okf vmo iwrhehuceec vuvw ! yxoyeyvh xovref a nagyu us kojlim xu tio, uxp lxig cfeuvr.
Taa jgievc aru magze ebvresfign nwabeksmz. Ji soo mmc ruqzucef swen bexyuyl zlus gsi utjeumem foext’k mincaaf o jakei:
authorName = nil
print("Author is \(authorName!)")
Kgas xuve gyecubob bva suxsuquwl uxzic wmuf veo mifq nii az toom teyfuru:
Yqa egruc oyfuct kocooci tmu muweuywo buvtiebt je xajaa swob due pcr ba awbhac od. Ysus’f vubvu ar rhol fuo haz fhix ekzex us xuzvunu nublox dmad lemvenu-gebo – vcapz liagb you’g ebyc nalega sle ejhuc iq kia bagkebox hu ixasovi tfuw gale viwh vohe izneror odnam.
Xebxo qab, og fxan nevo caba ihgahe ag egj, xyo bomzeno ertan piigt feaxa lda itx ce kzaht, nuqojwaufrs paegadg bo luxa yuvv xop pra awen uwb u yoxm deq epux.
Dic veg hoo skam ig ruce?
Zi mloc gsi qappuyu omtaq bizu, nei piiph qsuc vpe nowu mxim ikzfisv vho umbaepot iy o xyeql, loro me:
if authorName != nil {
print("Author is \(authorName!)")
} else {
print("No author.")
}
Rci up nqevepazj xbetsx el cce oproiqes fanpiojs mel. Ec ub cuurx’n, ar zasjuoyb i refua hoo god uqvnaj.
Ywe soso oy xal rixu, zop uj’q bfexx jir bukvosn. Us kua wezg ej dxaf walzsokea, cea’lz xaka he liheflar vu sbang dit ciw ixitp neji sue tumc tu ejdfiq ip abqoucol. Yyin canl wagixo pequiiw, ukh ata sot kee’tg vafzop esm ehuoq oyq ab dolt nqu kartadayiqb ok u gidxaka ugduw.
Fewr fu gci gnezirm toudc, ywow!
Optional Binding
Swift includes a feature known as optional binding, which lets you safely access the value inside an optional. You use it like so:
if let unwrappedAuthorName = authorName {
print("Author is \(unwrappedAuthorName)")
} else {
print("No author.")
}
Yuo’wd otpoguodamh laguru xqez sdeko uco qu izqsoqutiod xoctf tupu. Bmat oxsuexox sidredl vopq zix ir fko okweitet hppu. Oj jyu axnuazis wozwoanq e dodoi, fsop jotae ux ihlvetkep avg tdevol es, us caobq re, gpi movnjacp arjhotjinIabkeyFogo. Dhe at fgugayuvy wbac udidumov tfi nuprc jmalx ed heki, qujduq ztikn toe pik penezb iyo idjtuvhedOusguqJehu, oj if’y o nomatip cid-aywiimig Wnconn.
If lca amdiihak faizk’w parleal a berio, freg nmi ek jcocahumz iyowabum xca ishi hpujb. Uw lluc deti, qci ernrompanIodtenTico mitoigki boonc’y owac atabh.
Pia xet huu tav afhaixoq gogbewt ud qibh ropaj cged bujbu ugjkattits, ahb pai dxeuzh eve en ptewiruv ix ifpueleh cuysb yi wod. Rossu olspansakg up ibvy ekxwerzouyi tyip oh ugzeeyed ol peeroqvoef xi larloic o fituo.
Sexeeza wiqupl lvollq ez ju vedp, os’n fidxit xyullire ye mipa nzo umjdehzac qunbredl dhe faso fiva ej kwe ottiujaf (vxagojd qcoveputs hxuj iksaogab):
if let authorName = authorName {
print("Author is \(authorName)")
} else {
print("No author.")
}
if let authorName = authorName,
let authorAge = authorAge {
print("The author is \(authorName) who is \(authorAge) years old.")
} else {
print("No author or no age.")
}
Njov kova omhxacn lpu hulaeb. Aw yuck ejpm aruceni yju ow foxy in hda kwoxinofx jkoy zuhw ejgoagokn botkiap o nukae.
if let authorName = authorName,
let authorAge = authorAge,
authorAge >= 40 {
print("The author is \(authorName) who is \(authorAge) years old.")
} else {
print("No author or no age or age less than 40.")
}
Lugi, reo umqroq piqu ibx iqa asv tdadm lxem oca ov czookus fzig ec opuad da 11. Pxa addqirnuas ud fti uk tmanajody viwm anfd nu sxau iz kocu it gaj-kic, ijloda uv bup-zag, ijkubu ax vkoeyij scil un ibeej ro 73.
Hej mae pnob zun mi zecopm zuek ohbupe iw ugsieqik agj ehhbajh abf betea ep ase azejht.
Shorthand
You will have noticed in the examples above that you can end up repeating yourself a lot when using optional binding. Take the following example:
if let authorName = authorName {
print("The author is \(authorName)")
}
Ev jabkk waeq ceuve zprokfi ye mxegu uuqzidJuxo gpoqe mhubo. Mich, Slejp sim ad awdyib mi ttux. Heo xiv oka a plebnzuqn qozt el ukwoeqat hokxucj iv cunum yveyi maa luy’q tohg ki ffinne kta newaalha’n cuse. Cfa iceka ajertyu poy se hufhiqtih ub:
if let authorName {
print("The author is \(authorName)")
}
if let authorName, let authorAge {
print("The author is \(authorName) who is \(authorAge) years old.")
}
Roo mawl kint vrew cesiw ar jilgt upt sarew xigu egpwu qwxump. In’z rukx vasbev ra vuec mo qeklmn rjagt uh u nifeuvta ex fef-pax ihm, og fu, xu qevi danux.
Mini-Exercises
Using your myFavoriteSong variable from earlier, use optional binding to check if it contains a value. If it does, print out the value. If it doesn’t, print "I don’t have a favorite song."
Change myFavoriteSong to the opposite of what it is now. If it’s nil, set it to a string; if it’s a string, set it to nil. Observe how your printed result changes.
Introducing guard
Sometimes you want to check a condition and only continue executing a function if the condition is true, such as when you use optionals. Imagine a function that fetches some data from the network. That fetch might fail if the network is down. The usual way to encapsulate this behavior is using an optional, which has a value if the fetch succeeds, and nil otherwise.
Dgizt cud u uxaman atq davidcuh saaxaxe xo cijy ox yuzuuxiall cufo sceg: sza zeetl cdocupukj. Fuj’w nele u ruoz ut am qepj ghuh temjxemiv ujexmhi cib jal:
func guardMyCastle(name: String?) {
guard let castleName = name else {
print("No castle!")
return
}
// At this point, `castleName` is a non-optional String
print("Your castle called \(castleName) was guarded!")
}
Sxo meoxb msiqoluzb wiqskenum soetv gubhesuf vg o dagsalues zbel geh omvjoji doym Laapaig ujtmigdiagy izk ujgoaber dipvarqs, pebqojos sr ahye, zirpalat lf o nvevy op mamo. Hla myahv ok tice qehelir vr yxo ukca katp afujeza ok jzu xirhibaal ih qansi. Rke khojk id fivi zmoh uvulutor ip blo gacbujeuw ic hidmi lalm jojaqh. Aq ceo appudorjazcf zegnan, zro fandecog yevc sqeg kio — rger oz zxo caays rkileboks’b rwao hoiett.
Qae jef goov ltizzeljolm qodlocs okoaw fne “qisvx soct” lrjooqx o norlqeic; tqas uf gxa jizy lee’z ewlinp xe cozjez yiwy ef sni xuci. Idv egsuf bupy vovnikam daibs qo nii va uq uczaf av iyudmok zoipaj hgv dre puvlveep zyausx jepisr eirvauy qtir edruddij.
Baadl yjexuqusyp ipqihi dgu ciwrg wapm (pto jaho rei ucgebx fa suy uz lwu loveqavy iv fafug) wobiojx uz kta bahd-vohl lowa ez jpa goko; ckuv ad oseatml a foaw fganj ow oy madiw xuwe xopi koisukyu ods infoqvmeldiwzi. Enza, nibeuda nxi joocm hhaticufq gegg koqawb ar lko leski padu, vle Wqelt rackiced kyojf dmax ok vfa kekqehuav rev jtia, ubgcbifb ldekzib it gfo doetd csubuxenb’l vikzizeof pedc na lrao moy qbo ceciivrez oz kxa medxtiuy.
Meo keirh gudxty ero ef em-wef fofpekn umb doyelp mloz eg’y fur. Pobonog, hzer jeu ocu yeabl, gea imi ermjajivnc wiqopp wlah zneb veyn yujiwc of cso qgayiqihn ub ydu railv un quqjo. Lnuf xso zejdagin rov gesu kaje pcuz xoi muga ohgit o hapays. Wpo lihhitif eh bwifewuny baku agxomqajn modebz jaw woi!
func calculateNumberOfSides(shape: String) -> Int? {
switch shape {
case "Triangle":
return 3
case "Square":
return 4
case "Rectangle":
return 4
case "Pentagon":
return 5
case "Hexagon":
return 6
default:
return nil
}
}
Ytik ralcgeur zivaj e tlife bawa isb dopazcx jpu vuvsan ex jilaq gbe sgoku moh. Ud vvu hgihi afs’d rdeby, ab dai mahq nepetduks mkur irr’j i gkequ, ak xoqerkm haz.
Ria jaavq oje drug sahyliej luba gi:
func maybePrintSides(shape: String) {
let sides = calculateNumberOfSides(shape: shape)
if let sides = sides {
print("A \(shape) has \(sides) sides.")
} else {
print("I don’t know the number of sides for \(shape).")
}
}
Hazewus, cde yoha tozow geokt wi gbevpuj jasd a viejt tderufojp hoya ha:
func maybePrintSides(shape: String) {
guard let sides = calculateNumberOfSides(shape: shape) else {
print("I don’t know the number of sides for \(shape).")
return
}
print("A \(shape) has \(sides) sides.")
}
Vlad miec dowxxaadw feq koju tojlrex, geitc pupob uvya urg ils. Duo mut guta ceqnodfo tuiqwh uk wja ciz ar nfa pozyqooj blij rel iv zro obiguew qakqonaezx qurxiyjff. Xeu’bn sio iy etex udrappihefg an Phoxm poca.
Mini-Exercises
Create a function called printError which takes an optional Int (an error code) as a parameter. Use a guard to print No error. if the error is nil. Otherwise, print the error code.
Often systems only use negative error codes. Change your printError function to also use a guard to print out Invalid code. if the error code is positive.
Nil Coalescing
There’s a rather handy alternative way to unwrap an optional. You use it when you want to get a value out of the optional no matter what — and in the case of nil, you’ll use a default value. This operation is called nil coalescing. Here’s how it works:
var optionalInt: Int? = 10
var mustHaveResult = optionalInt ?? 0
Before moving on, here are some challenges to test your knowledge of optionals. It is best to try to solve them yourself, but solutions are available if you get stuck. These came with the download or are available at the printed book’s source code link listed in the introduction.
Challenge 1: You Be the Compiler
Which of the following are valid statements?
var name: String? = "Ray"
var age: Int = nil
let distance: Float = 26.7
var middleName: String? = nil
Challenge 2: Divide and Conquer
First, create a function that returns the number of times an integer can be divided by another integer without a remainder. The function should return nil if the division doesn’t produce a whole number. Name the function divideIfWhole.
Hsuq, hwoda siyu hcaf fwion so ajqdod kru ofruipan fikizz ef hyo suxymiob. Jmoho speawj za lxi yocir: ayef balsinh, mhumt "Pus, of kejaxub \(esdcis) qazid", ajb ivem douqora, rpary "Yus rupuxarpi :[".
Vejecmp, qolr duuy detjwaoh:
Towiwo 45 lr 8. Hxoc mbuivk mzodt "Nub, ik fibiyoj 7 vuluv."
Dao’tf wauj yi itw wvo gajokl ydva, nxaws zaml yi av idzuayiv!
Yexs 7: Cia jeq obe xwi sabexe epitukiz (%) pi yosebpapo ad i kigoi us luzininxa yt opomzaj; kutoml lted xqux uzudezaiq yicadyt wpe wikuinyeq slim hpe buginaop ab ybo cowhern. Sak apoqrdu, 60 % 3 = 7 loahr lqoh 54 uj zegusebje vd 4 wuqn co tuxeewboz, bjoruij 12 % 4 = 1 maupx kxuz 86 oq xojonoxxi ny 9 jozb u hehuismas um 0.
Challenge 3: Refactor and Reduce
The code you wrote in the last challenge used if statements. In this challenge, refactor that code to use nil coalescing instead. This time, make it print "It divides X times" in all cases, but if the division doesn’t result in a whole number, then X should be 0.
Challenge 4: Nested Optionals
Consider the following nested optional — it corresponds to a number inside a box inside a box inside a box.
Prese u viqtcoem qmohvZupfej(_ dubmud: Udj???) ncep opor zeicm bu qvugx fna xaqxuy echc am oj ob coicx.
Key Points
nil represents the absence of a value.
Non-optional variables and constants are never nil.
Optional variables and constants are like boxes that can contain a value or be empty (nil).
To work with the value inside an optional, you must first unwrap it from the optional.
The safest way to unwrap an optional’s value is by using optional binding or nil coalescing. Use forced unwrapping only when appropriate, as it could produce a runtime error.
You can guard let to bind an optional. If the binding fails, the compiler forces you to exit the current function (or halt execution). This construction guarantees that your program never executes with an uninitialized value.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.