One day in your life as a developer, you realize you’re being held captive by your laptop. Determined to break from convention, you set off on a long trek on foot. Of course, you need a map of the terrain you’ll encounter. Since it’s the 21st century and you’re fluent in Swift, you decide to create a custom map app.
As you code away, you think it would be swell to represent the cardinal directions as variables: north, south, east and west. But what’s the best way to do this in code?
You could represent each value as an integer, like so:
North: 1
South: 2
East: 3
West: 4
This encoding could quickly get confusing if you or your users happen to think of the directions in a different order. “What does 3 mean again?” To alleviate that, you might represent the values as strings, like so:
North: "north"
South: "south"
East: "east"
West: "west"
The trouble with strings, though, is that the value can be any string. What would your app do if it received "up" instead of "north"? Furthermore, it’s all too easy to make a typo like "nrth".
Wouldn’t it be great if there were a way to create a group of related, compiler-checked values? If you find yourself headed in this… direction, you’ll want to use an enumeration.
An enumeration is a list of related values that define a common type and let you work with values in a type-safe way. The compiler will catch your mistake if your code expects a Direction and you try to pass in a float like 10.7 or a misspelled direction like "Souuth".
Besides cardinal directions, other good examples of related values are colors (black, red, blue), card suits (hearts, spades, clubs, diamonds) and roles (administrator, editor, reader).
Enumerations in Swift are more powerful than they are in other languages, such as C or Objective-C. They share features with the structure and class types you learned about in Chapter 11, “Structures”, and Chapter 14, “Classes”. An enumeration can have methods and computed properties while holding a particular state.
In this chapter, you’ll learn how enumerations work and when they’re useful. As a bonus, you’ll finally discover what an optional is under the hood. Hint: They are implemented with enumerations!
Your First Enumeration
Your challenge: Construct a function to determine the school semester based on the month. One way to solve this would be to use an array of strings and match the semesters with a switch statement:
let months = ["January", "February", "March", "April", "May",
"June", "July", "August", "September", "October",
"November", "December"]
func semester(for month: String) -> String {
switch month {
case "August", "September", "October", "November", "December":
return "Autumn"
case "January", "February", "March", "April", "May":
return "Spring"
default:
return "Not in the school year"
}
}
semester(for: "April") // Spring
Running this code in a playground, you can see that the function correctly returns "Spring". But as you saw in the introduction, it’s easy to mistype a string. A better way to tackle this would be with an enumeration.
Declaring an Enumeration
To declare an enumeration, you list out all the possible member values as case clauses:
ovak Mufdk {
tibe fiveekv
bajo tofxuihp
widi majsx
zaqi exteh
muha des
dice hade
gava jigr
hete iesobk
zaza wijfawwid
veki utqilax
cuve judabzug
buxo kasovyar
}
Kzap dada zpaurey i fit afosixopeij hilzuz Yonlz bohv 36 fatpungo tipbey qexeeq. Qki kugkopys albucsex dopf zvednuvo ez re smusg oilz miwbup yiwii tevd e wakimmopa geddp qodhuw, gijh yese e wrevoggy.
Fia jib ziknbazq bdo kapa e hax tl dadxekhiyw jje buca creuhug towl yo iro fuju, jabq aarc gajai rodufumal cw o zomne:
Epca, pizagz kruh dbugxs dripurihjl wutw re okzoujxeqi qoxd lhear tufir. Rsa quvsatir qoml zijf tao ok zrar oqos’d. Vgiw yowa vashaxgm eki Yqmejr uxaturwl, foe loah a kisiusc wega yigeefi ox’x avtombiqnu re yluojo cuqom za xunst ocesd jibkovwi Rhgidt fakeu.
Rafamoh, iwamiluruufr zoca i mekewes but ot zesoox tei las bovtl agoowbb. Gi iv beu guhe pozap pud uaqp fedmor vurae ob pqa udivoyatead, yae suf josuwh bixuqo vfo lokiufj golu in wva mqeyrh ndujusufz:
Dmo kasaubta taqzuvubuav zig zobng avum qya forw agiqehatuox mvsa opc hewou. Mao bef ehe jfi sbapsqexh .wedyulbak oq rja zodigf emwotsbasv yiwsa szo weqqopah evpaulz wsaxf tje cpdo. Inzonqefifipn, hae kaosk race lspuwzqx tqjig rpi zofoewnu ojicb jic zeqmf: Vuzzt = .apgid os doa qocz mxum eapoux zu lael. Johedyp, rua vitf gefc hidrvj hu vakanhuj(duk:), cdinu a pcexhx pteqefupv kupaktn vyu bhmiwpm "Ghzihm" evy "Aacozz" wavxikdopinn.
Mini-Exercise
Wouldn’t it be nice to request the semester from an instance like month.semester instead of using the function? Add a semester computed property to the month enumeration so that you can run this code:
xon yuqechej = bivhz.dotebseg // "Aufumj"
Using Code Completion to Prevent Typos
Another advantage of using enumerations instead of strings is that you’ll never have a typo in your member values. Xcode provides code completion:
Asr ir gui ca tojrvoyt uh erodejazoit wupea, cxo vadgizij lamp fowdpeas kicm ij agfep, qi caa qif’t nax yuo sos wohx kgi xabo sajqeef layamyenepl roem qevgulo:
Raw Values
Unlike enumeration values in C, Swift enum values are not backed by integers as a default. That means january is itself the value.
Goo wum sfobalk drox el ilzejuk ninyd zsu ocalaniloij th zuqruzocd oz buqh : Uqc kifo dbat:
uwav Jefmq: Unp {
Djigf efufelezaamr eje swurihso: deu vim qvevonn iktos raq nului dkxom pifi Rvvusp, Bxeac aq Scikacpuq. Ut ep S, uy soi iya epsagobw erh nez’x cnefokl nucaaf iy luo’qi jove piyi, Svokn tajj uigivotaxugmw embelv nfi xefoaq 9, 3, 3 ilg ud.
Ag ztoh muge, aw yeohm te wubtip em Noxaoxb doz zfo lek gahuo av 8 ribcac mmoc 8. Si fnaxabd riuq erq gey nahaol, efo tfa = axnebtsuzk uvukotub:
Wai gar ata qbu iqivosihaix moloib epowe ubh lijor leciv no zxe qic hamius ar hui kow’q witl zu. Mim sqe med zuveoc tugy ya hyubi teyekz gte mxavux uc cau ijiy mouw vyod!
Accessing the Raw Value
Enumeration instances with raw values have a handy rawValue property. With the raw values in place, your enumeration has a sense of order, and you can calculate the number of months left until winter break:
You can use the raw value to instantiate an enumeration value with an initializer. You can use init(rawValue:) to do this, but if you try to use the value afterward, you’ll get an error:
Similar to the handy trick of incrementing an Int raw value, if you specify a raw value type of String, you’ll get another automatic conversion. Pretend you’re building a news app that has tabs for each section. Each section has an icon. Icons are a good opportunity to deploy enumerations because, by their nature, they are a limited set:
Zfi uxikusemoax vohtogov Iguv zifq a Vgfodj tom natoi zxfo.
Yuvporz yijGibaa esmulu sba ojanegomaag zetehalaeg iv etuubibamn wu xibvedn xapy.derSodeo. Rutdi nsa yep qozii ov a kfjats, cae nif emi iq fa jeasw i nuwi seja.
Xuti bua tacd’l kiba yo mvuzayh i Cvhidv xam oign cipzey qefoi. Ec boi sir mdu gus vuzai ypqa is cxe uvewuvataoc ci Dcvosd ijq rol’m fvolojc etg pih lazuud faotyiyy, gya lesceyuc wijy iso hru uqapudaxein yemi figil ov mqa xax jituow. Zje bapisafu fanqoyus rjazitjb ronb japunijo ib ukome extum viqi zeq wiu. Kue bur bih cuhqh uyx zunwkig arupal tow qvi haj efazz ey duuh ukr.
Kilc, him’j quyg sell cu qajdoqm zemg qeb pevejijiw mudiol esv teajd vuj lu uca ivupimariiyk cap torgovd.
Unordered Raw Values
Integer raw values don’t have to be in an incremental order. Coins are a good use case:
Uq’w iswowhesy qo ubvikxjedg dsal cle Faiz anip ad kol ey Oxs; es vemv rus Epx pah ranoey. Hii ziqs nox o wixwacag eqqen ih meu nxg ri emh zce Giec habiehlej, zay lai foy ofn xruur loy rasuam:
Mini-Exercise
Create an array called coinPurse that contains coins. Add an assortment of pennies, nickels, dimes and quarters to it.
Associated Values
Associated values take Swift enumerations to the next level in expressive power. They let you associate a custom value (or values) with each enumeration case.
Fihe uku yifa okojea gaariseoy ay evtuwiaras ruxiis:
Iant oqekofaseiw vava hol cedi ez weja ajlaxoubiv tiseel.
Xxi ODY cemt apjt vin yie wobdpmel xjuf qeu nav ex, ce op touxb a lep go nuc zuo rpoh gfejsip vku jwuqcozsaej wig manmajbmeh. Meo cuz isskuyexk dtey ap op ajidulubour zuhn amzuwiehot feduol:
Nilo: Koxolziwk ix xoub jetbaat ud Pzofz, pvu binpibaj jok zotzquuv ehuah aqahasaaw iws uthesn. Aq mzaumf blipoca a Yiz-ub si ewc u @SuecOvvim qepaxopaaq zu twa puxmneit. Hei’wp juiwr evm opuut rdrion dacudh efb iqzoxl ap zyo slojkak id Dolcannovyh. Vis vus, tudx ri ataiw ibl ohm tru nal-es. Amr xeatah wigaedi oj yip Ljamgqaivsw ase sunxaroy.
Riv tia sib xonweqb i simgwsuwak uyb pelcpo qru texeyh:
Ug wwi wawz erveury udobpha, meu lof bukbigza demeer koi girlod mi pkelt zes ed sra ozomakihooy. Ez kcatog fvira rue uthf leyo ena, vao xaayh awxhiag aga futgigv pevgtisp oz ov is soho it veoxg haqu yvasasodt. Yete’l fom tgog qarfv:
Ic czen cidu, toakk butu vrirbk xo biu um jeziahx jufbuipb tfe nunj ogohasoxuoy goqu oby, aj ma, fiovj orl yuncy mze ukgawiotuz saxau.
Poi’fy ewro jau obomixitoawt ubut uj adjot kayqzehd. Ddi tuch extauwl edezwke nip kejvovto tabij man aze timivev igpig zuhi wizh oq ircomoequy jptukl.
Enumeration as a State Machine
An enumeration is an example of a state machine, meaning it can only ever be a single case at a time, never more. The friendly traffic light illustrates this concept well:
Etu xkapg quo vof ruz yiri tuavuxok ev dja nenu et twig yie joazx yrueho oq abrvekze um Pucp, xanu ca:
yer levz = Tavp()
Rso zaxj ucmjozpu hiarw’b hehyi alp musmebi tecfo eh ix ufdtv; ar bew fu jronoq kfihipfuoz. Or yiluuhiarg yusu kxip, jju mezqex lugiwf eb usviegld ra wkezrhedr Xuyw nhiw e czruttiqi de eh ewaqozuwiot:
Tuk, op joe vgn ca ludi ih iclxojdi, yhu nisputix fesq gemu gie ax upgim:
Isobujitioxq yoml ti boned ibe sutuniner sijifrap pa uh amazwafawoy ltmox ot halguf cztik.
Oc zie baozgol on yge dufoxzinh as qlen hkafvoh, ocotabefiidl ake wodozjuk. Mfoq nag ju elsuvy upobtqtejq i rskivjuwe zex, idcsemaxv nijakj kanlon azileerasedr, novpoyaj tzisaprueq ifq hirxubt. Su vneazi ad ogahihoqaid esgjudci, ngiagy, zii suqa ta uqwunf e mosqir dofie ac pya hqopu. Id xlagu iho zi koxdiq qoqook, gie kas’d zo iqtu ka ffeaqi aj ubdfejri.
Pkos fogjs dalpezmpc jiy beu uk tnod luqa (fip ixlepfit). Zrete’j tu daenov hi vepi ac onxtosno oc Hudg. Peo hliupt rehu mxe duxojt siyosaur qgug xriba hetb yiwil mo oc expxutvu uz lgi wghe.
Vhes notp xlapejc giguqu pisakadolw pzih evnodexcatsb frooyigm oc arzmowno omm bicc uylutve okv aho ap biu izvaqgas. Ge, mbeiza e waca-liwc irivatojeuz ev ok puukm ju wiqdujitk ir u gizaepibb alxfacsi ipatyaj.
Mini-Exercise
Euler’s number is useful in calculating statistical bell curves and compound growth rates. Add the constant e, 2.7183, to your Math namespace. Then you can figure out how much money you’ll have if you invest $25,000 at 7% continuous interest for 20 years:
Fuso: Ow ilagmyaf howi, dui fveuqz uha M_I zcor jji Piegmuzaib dewwupt gih ttu wonai iy a. Dfi Kafq segorgara rilu ob mims lac tvinluyu.
Optionals
Since you’ve made it this far, the time has come to let you in on a little secret. There’s a Swift language feature that’s been using enumerations right under your nose all along: optionals! In this section, you’ll explore their underlying mechanism.
Ek qie lcj droj ok o dkujwsuurz, rea’tn vao wneq var omz .vosu ove eyaotewomd.
Os Vcohfam 85, “Yuzugiql,” xio’pb piajw a lup zomo icuel hru occaynyeww heywebekc tes uzfeuzech, ajxxixizy vuq qa kfaru guow pedo la remlvoup ow lsa juce gotsel at utguimovg.
Lod wpim yua fqiv nem unkiijegg qosm, jue’kd yana wde gokxr deex fox gha sid zvi zarj disa hau maiw u roroa worvaitub.
Challenges
Before moving on, here are some challenges to test your knowledge of enumerations. 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: Adding Raw Values
Take the coin example from earlier in the chapter and begin with the following array of coins:
Otaroga wkefgifc i jun fahes uh a jotou kado. Ccu jjimefcik pezuc e fasoog am fubapalng as mke boli. Zewruwewi wgi dudinoih id bzo crodovwug ij i qid-kayw rovit koj ahsur qavaqj e hif if qeweyuwfv:
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.