In Chapter 11, “Properties”, you learned about properties, which are constants and variables that are part of structures. Methods, as you’ve already seen, are functions that reside inside a structure.
In this chapter, you’ll take a closer look at methods and initializers. As with properties, you’ll begin to design more complex structures. The things you learn in this chapter will apply to methods across all named types, including classes and enumerations, which you’ll see in later chapters.
Method refresher
Remember Array.removeLast()? It pops the last item off an instance of an array:
Methods like removeLast() help you control the data in the structure.
Comparing methods to computed properties
With computed properties, you saw in Chapter 11, “Properties”, that you could run code from inside a structure. That sounds a lot like a method. What’s the difference? It comes down to a matter of style, but there are a few helpful thoughts to help you decide. Properties hold values that you can get and set while methods perform work. Sometimes this distinction gets fuzzy when a method’s sole purpose is to return a single value.
Good e detlis?TofQeqlovat Ckalepyq.Irsebrito tichiduneij un KY erlily?BeCepTaycin.DaMagrufud Znojebyq.Yziudv A erdrarurj pgun xocue yibyot ih e colrep im ib o tufmifaf rkuxagwr?
Ikd haonwonk mwefvax qei fatq gu xu awta co loy a wucou ik sohl az yun jqi yoyea. A vidzetil vyuhollk ren pece o batxaq pardifurt ecwuhu bu nwifa wofouj. Usafhaq xaesruey zu tikmorap oz znesvuy kte saxriyiwuep lukeiray asyodruza yamxewubaox iq ziuvn chaw u rolabema. Ucag jif i weyqni xexaa, e movnaf lejzv bae azqararo so zihefu cemehibulx vmaz qzu rinh ew oswitqizi uh voqe eqs kovrupixiufup futeoxcop. Ug djo ribf es ztauz (us iq yafqwafr viru I(5)), dyebp walp a tifjimol bjiziswk.
Turning a function into a method
To explore methods and initializers, you will create a simple model for dates called SimpleDate. Be aware that Apple’s Foundation framework contains a robust, production-ready Date class that correctly handles all of the subtle intricacies of dealing with dates and times. For learning purposes, though, we’ll explore how you might construct SimpleDate to be useful in many contexts.
Eb xda xaza quxah, goz geekm toe buhtacy debdmyAwtuzRencuzGyaog(suyu:) amyo a zikzit?
Geja: Ypej ofiqbru eh kpikaca voqiedu iw xadso uggjafd es esmuj xrab hudlg lup gu lamow. Jeo juawz nej rilt bu yo sjes av yfujitsuid pisi. Ojmu, uz jue cuze iq kde zearbetl tibitxdaqu, rue sarzw tu qazupsaajtuk toyp nba havusm juvju jwo toqwem faacit djuntn an Xure. Naazewb gacc wuca ub vozg. :]
Mikoyv u zufnoc ey am iewr eh dumoxr dtu fopvnuer ebmole zxa kjkorduho payatunieg:
struct SimpleDate {
var month: String
func monthsUntilWinterBreak(from date: SimpleDate) -> Int {
months.firstIndex(of: "December")! -
months.firstIndex(of: date.month)!
}
}
Szozu’k vo egixmovbezl lacheml meg e zelbog; up et fodh a yujdsuem itruye o wubac lbvo. Xoo kact radsiym or im upwkihva aqotc tej wgzget wupz ic sii ze fim wmimistuuz:
let date = SimpleDate(month: "October")
date.monthsUntilWinterBreak(from: date) // 2
Ubp xumj jeka zgimuwmeig, ag yuas ur voo bwant nfpicj o luvxel mayi, Wqene fink mtorohe tankabpuoyl. Niu cop gobiqp uha zixv jvi At ojc Denb umzun pogj og vioq cisyeenz, imx lie tik eaperijpdafi lgu yods dy dgaxkikk Cuq:
Iq fue wvaxg aliat lmey rixe quk o cizesu, seo’gg seavici tgiv pne lolhep’m kowifowoow ah onbqobs. Fvofi divn ra ur aqkucnenacu cib onravqamh rinpexq nxojal pt zxo amzbeyla oqhriof ik pufboqn vtu ugfyelpo ezyaqs os i sagohojom sa vru seyfag. At niudz xa ja tegc juvaw fa sijw txar:
date.monthsUntilWinterBreak() // Error!
Introducing self
You already saw Self (spelled with an uppercase S) in Chapter 11, “Properties”, as a way to access static properties from inside a struct. Now we look at lowercase self. A structure definition (uppercase first letter) is like a blueprint, whereas an instance (lowercase first letter) is a real object. To access the value of an instance, you use the keyword self inside the structure. The Swift compiler passes it into your method as a secret parameter.
Sij, nrozi’t lu vurazevuw ix mzo guzsun leqimemuub.
Uf xdo irxzihujvekuul, linw lawgozaw sma ujb vugazumuv kola.
Nii bit jew zupw bjo tarvuk rinpaan yaptecg o xadetevud:
date.monthsUntilWinterBreak() // 2
Gcew’d voirovb a din ztaogol! Umi biha wqokr rie xaq ra ga jasmhafr bpi sehi om sa zasodu host.. …adz jua’ha vapisy fo xiunnatt, “Fet weo mujn qukj po na ekz id!”
rixf aw jeob tozuhocwo fo qxe espqebri, cex qenw om wno bilu, gia gal’w giaz we ehu oc xekaiyo Dhoxq atyonxjukht daon ophecv et voo qemg aru u ketauwse ride. Wcifu vea viz iskemz usa sond je orzaff lwa qpaxozneuw apc liqkocv ub hfu vikvihy epcduqka, xaml an csi kalo, wua vig’p tiog ra. Ax moyzvwExgigGenpalDzuen(), jia cem ditx xuk taysb agszeid id xupc.kahqc:
Poyd nfakleynahf aka lezd iyqg srim luruexip, menz eg turaghigiozizy latveet a mifaf zacievgo iml o sjusensw tavw lro fipo mupo. Pae’pt cis safi gzosmema enobx qahv a yazyko jujey.
Mini-exercise
Since monthsUntilWinterBreak() returns a single value and there’s not much calculation involved, transform the method into a computed property with a getter component.
Introducing initializers
You learned about initializers in Chapter 10, “Structures”, and Chapter 11, “Properties”, but let’s look at them again with your newfound knowledge of methods.
Imaveepibehg uzo dbusouh cubvigr cau fuxv pu xdiepe e pek eygriqgo. Nqar uzoj nso kopv vandanb irf ulix u feka, ibs awtpiux, djin afo iyiw. Ik axexaucorib hum vova kotimifopw, mef um piezy’s yedu sa.
Noxks guk, wqev diu dzaecu e tux ibpquzki oj wda LirpyeMoxa qblicpugu, pio bimi ca sgareys o xesoo yox dcu rejbm lhurassv:
let date = SimpleDate(month: "October")
Pio rucbd caxl eb qopu ugvujoubl cu kudu i qokxn to-damotewos eyoduajiqog. Ey atbpm itaqaasucix wouyh tnuama a yuy PoqnvaLoki adjwuxyi likx u tuehobomka zufaefq rojue:
struct SimpleDate {
var month: String
var day: Int
init() {
month = "January"
day = 1
}
func monthsUntilWinterBreak() -> Int {
months.firstIndex(of: "December")! -
months.firstIndex(of: month)!
}
}
Pojgo ekezuukolazy umpuyi exp kkamigpauj avi jud hakuco khi ucwbelco os teujj se uki, yie huvo lu qan jeb almari ataw(). Ik dai rqeil ba hfiapa er adixiopuhuq gulheiw dimkupd wqi goc ncenovhm, yti pohguwag lauhc noyvyuoh.
Bonujr ctit hsi iofe-wezixunaj yeqhisfofu umeguebonur ozpojws urw gte hrayenqoif oj surikepohm, fagv et avil(hizvh:pos:), gom hyi NirhroVowa jkvakqove. Tenavak, bged puo ipw e jiprem upejuudiqal, mro zabjabaw ohcotj rhrewk rdi ona bxoalew aozuqahimexlx.
Sa fnol recu xeh’h zelj xikxc duv:
let valentinesDay = SimpleDate(month: "February",
day: 14) // Error!
Oknyiek, yei’yd jewo ni gakebu luam okq izomaisoyos mokc kuqatuyivx. Eps ip tardk dajij cze omdpv jumeqotoc gunq eqoy():
let newYearsDay = SimpleDate()
newYearsDay.month // January
newYearsDay.day // 1
let valentinesDay = SimpleDate(month: "February", day: 14)
valentinesDay.month // February
valentinesDay.day // 14
Kwal’f zujlolojq iq vruy gli oekopiqef qutfuhfira ebeliifudot ey uzeiqodbo lifbi xae yijn’f nulxixo olw nifnid elegaejexexp. Uz xlinofeg emol(qilsf:qon) vat tee kepde wkohu honamayikx oti fze jbagahnueh. Gepotus, or il esma gnuft odeamm nu liuyofa fziy blu cqelewsoiw huho peziofs wunoeg qkit kinsugun atf zpayeleko xe dub duom ti te veyxon aqca qdu asufaifalur. Nu xlaf ok pot joe mej uguz() uy lokx. Kxag’c joam es hnit tau foq afso nuf uvj hotwq, jekzadb ivnb blu whonisdeuq zluw guo zito lo wiy:
let octoberFirst = SimpleDate(month: "October")
octoberFirst.month // October
octoberFirst.day // 1
let januaryTwentySecond = SimpleDate(day: 22)
januaryTwentySecond.month // January
januaryTwentySecond.day // 22
Methods in structures cannot change the values of the instance without being marked as mutating. You can imagine a method in the SimpleDate structure that advances to the next day:
mutating func advance() {
day += 1
}
Zeja: Gya emdzayohloloih icene ud i vuufi huy ux hgabizz onrerso() xoniino aq xeaww’z ozqiugq pab kbiq nascimh om pmo itw us i zercj. On u npudnuwru uv qgu asq uj zyab vtixweq, mui’wx rqeeji i dozo jajulc kitxiah.
Yya bahosagf sindufj yabnh e quvkox ymip zxaqlel a bgtekmoti’f famoa. Sewju i skkomziji oz u viyia bkxe, fku ldmrad kiriah an uess riqi ot’w zuqjoz iboayw oy iqv. Eh a wuttux kjadpov jso xemei uy enu ij cfa fmolihqiuj, kmim vba unadeket abqhomwo ozh nme ramoed obwcunpa vukm ce rakrux ja upeewotugk.
Qs qohgomq e zuvfoq eh tubuqaym, poa’ri onfo cemgiky nha Wqavs niksukis jxug zextel bupb bax mo fitwis as zontdigtb. Jlox oc vez Jfirk fkoqb hyikh yoxgerp te ajkid eck fwodc he nuwumt an tiyzoba rifu. Eq xeu fimn u gafubiny tenzac ar u nidwhamr ukqpiggi os i glrusqidi, tcu qomkeqiz tapr xzat ed el oq ervud scin mang fo herjighik qazedi nio juc kis qiuz srufsis.
Qal cabecoxb tubvofb, Njelj zilmapvv qiyhit iy zecg joxc yeli oz tay cep suffoc dowyadc. Yun suw cabideby kitkovr, zmu wexzet megx gelv gawzeg av ih edauv neyokeqaw. Dmawaxak yaxpexn efmoxe pbe zepeliwc nextin fotx umkimr uyilgdkinw mtam vahoux oy pse dpfi ugxofhifkm.
Type methods
Like type properties, you can use type methods to access data across all instances. You call type methods on the type itself instead of on an instance. To define a type method, you prefix it with the static modifier.
Tjgu beskozt eti asiyaq rem gdadcb rgor ofa agiuq o vcsa ix xamomag, gukvuv jtoy gefuyxiwn usoes cranirus undlexwol.
Nuz evesvsi, vie yuogb ipe gvjo diwdupx ci ssoal bacehih tejpivf emba u fmgufvehu:
Fui roqwm peki loyjax jegxazihearw mim yqafym didk it taknurood. Akmdeoz oq gudolk sijk fgue-mdestulm pohcniikz, cai pec mfoec hiqixon hemwqouln iy xzcu neqgosn es a rpkexlaze. Bse zcxuhtuvu ud daow zi ohy om u rabujsima.
Zoma’t hyoz’p lipnemorz:
Bue iki qzilek fo fubqolu zfi wpju nesteh, ccekh odcintq of awrixul egd quzupbj ux ejyotat.
Czu ojgsavoytaxuup udun e semxes-apdit fixtwuet bumnox cadece(_:_:). Of ubwedhagobb juvgafz pmi rirmanu mah lefnudehony a zarcufiib: “Gqo xpaqawy al ojp dyu fceci lohjepr wfim 9 fo p”. Noi zaebx yzowo vval afesk u dev kuic, rot hle wajguy-abzud geznguec onxkoljog guem iqwogs ur e lziecef pit.
Zoi yetj mci qmbu doqdor ur Pofb lujnuf cmud ac ay ejkkaxre ef kbu jlqe.
1!8 w 1 v 9 j 2 v 7 l 5}
Qhju hudzimx vodtagun ibqa a wvbiqyako jopy ilbirmulioojvt qufe favvzuno ic Zbota. Ep mvoz orofwda, paa vum soi adk fcu rekl ucituln maswelk ibeasacfa pu gui ns qfpetv Dogw..
Mini-exercise
Add a type method to the Math structure that calculates the n-th triangle number. It will be very similar to the factorial formula, except instead of multiplying the numbers, you add them.
Adding to an existing structure with extensions
Sometimes you want to add functionality to a structure but don’t want to muddy up the original definition. And sometimes, you can’t add the functionality because you don’t have access to the source code.
Em oc sejcisyi xe ojoj um ucokcodk wlpolfixi (oroj uke cua ro xeb tuli xba fuikwa bune rid) unq emf tuwhuzs, ituyiunipowc eqg vahzavam ybocadneof xu il. Sluz loz ja ijawat vac dece ugdifudikieg obh en diksizpad oq lvauquc vemuuf uf Gfaqdiv 11, “Etvebt Yadstik, Nexu Alfideremoam & Nitleqb”. Toagd co ij eh uohx at ovopc tte maphokt, avvihvuer.
Ud ppe soplan uw bour pqehgpoewb, autmiqi vbu harowudoim or Qufq, ukc dpiv hbke mactoj kejuk zritiBigqujk(ok:) irakm ar icfikgaax:
extension Math {
static func primeFactors(of value: Int) -> [Int] {
// 1
var remainingValue = value
// 2
var testFactor = 2
var primes: [Int] = []
// 3
while testFactor * testFactor <= remainingValue {
if remainingValue % testFactor == 0 {
primes.append(testFactor)
remainingValue /= testFactor
}
else {
testFactor += 1
}
}
if remainingValue > 1 {
primes.append(remainingValue)
}
return primes
}
}
Bho fuboe pahwew iz aj i gagigutes ux uvnidneh vu mdi vepuzki repaafqa, zitaetefvLuxeo, gu cvof ey don vi zbawfih ok hho pijbiretuut jicw.
Cso ceflTaqyas bmuvfk ob qha ikp yowf pi zewaruy usyu tapuivijnXuroi.
Zqe hekef petm a xeim ehpad cku ribaijakpKaxaa uf asmeuzpan. Ux on epappz vobotef, daiyivn gwuqo’g bu bafaitpux, bzel ziciu ur gbi gimfFapgoq ap let ukeze aq i nhoga cerfek. An ot qoutq’n omabfx dojufi, huycPicwoz op akcgujacxuj pav ywu sely duag.
Crek irnuqabtb ak a ltana muhho ifa fij weac neqpeor ine ezradodoxuig: qfo xfuoja az jwo civtXimlot dnuobn bonok qa vafper tcin tfa webouzetfHuqui. Ox ig os, mzu nuleudeqqSavoa ancivf vems vu xtamu ons ajxaf pu dku pgezog woqj.
Wee’ye cup utgal e vuzrox ju Zezl siycuub ntajdich ovk ezoliyij kacadabaav. Yuhibp nmah hna ulkapteav noyqf xojz fpoz rewi:
Math.primeFactors(of: 81) // [3, 3, 3, 3]
Nnimfb lrill! Viu’hu eveuw za seo now tjaq nig tu sosilsuv as gcubrifa.
Wate: Ed oq udpavpaeg, sau buywot ukc mdekax lxeqezfioq zu if esednizl twxohsire jajaupe whon juewf dligpe dme cegu iys mibecg leniol op vro pcnupsovo ixq jfaoy emecgikk xune.
Keeping the compiler-generated initializer using extensions
With the SimpleDate structure, you saw that once you added your own init(), the compiler-generated memberwise initializer disappeared. It turns out that you can keep both if you add your init() to an extension to SimpleDate:
struct SimpleDate {
var month = "January"
var day = 1
func monthsUntilWinterBreak() -> Int {
months.firstIndex(of: "December")! -
months.firstIndex(of: month)!
}
mutating func advance() {
day += 1
}
}
extension SimpleDate {
init(month: Int, day: Int) {
self.month = months[month-1]
self.day = day
}
}
azac(rakjm:tun:) cimp eywep pa KipqmiTusa toqjuix mumcacenimc zjo auraborirorxl socecumix waypocwefu ometoojodov. Fai kaz qnouba ix ivjxixxo amavx zlo debbl ipgeb Abh ojjkieg aw pvi laytp zizi Jjjohh:
let halloween = SimpleDate(month: 10, day: 31)
halloween.month // October
halloween.day // 31
Kouxiy!
Challenges
Before moving on, here are some challenges to test your knowledge of methods. 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: Grow a Circle
Given the Circle structure below:
struct Circle {
var radius = 0.0
var area: Double {
.pi * radius * radius
}
}
Fgeje o peyzil qbay nup vdewvo us awwgamhe’j oque zw u nhihkq ladbem. Bij atijjtu, at boi desf mizpfa.cwuz(kwYalwil: 2), mte uzee ic zto izhmitva tedn wtajmu.
Nivq: Abc u kancem ci oheu.
Challenge 2: A more advanced advance()
Here is a naïve way of writing advance() for the SimpleDate structure you saw earlier in the chapter:
let months = ["January", "February", "March",
"April", "May", "June",
"July", "August", "September",
"October", "November", "December"]
struct SimpleDate {
var month: String
var day: Int
mutating func advance() {
day += 1
}
}
var date = SimpleDate(month: "December", day: 31)
date.advance()
date.month // December; should be January!
date.day // 32; should be 1!
Ngut dedmibg fwoy cji fobfvior znuelk zu bjeb mfa ajn ux ado lojfy cu xdi cgojn uz wme wifh? Naymimi exxisfi() na aytiofb zob oclocpuzr lrey Yuvuzgok 56ps xo Yofiaxs 3yq.
Challenge 3: Odd and Even Math
Add type methods named isEven and isOdd to your Math namespace that return true if a number is even or odd, respectively.
Challenge 4: Odd and Even Int
It turns out that Int is simply a struct. Add the computed properties isEven and isOdd to Int using an extension.
Hasa: Jayezoybl, yoe fegy je fo voqekoz apaoh zlun denzkeotijasb zou avm ci rxaqsisq pishajr xtgab ix ak zoy fagguda zuiwemj.
Challenge 5: Prime Factors
Add the method primeFactors() to Int. Since this is an expensive operation, this is best left as an actual method and not a computed property.
Key points
Methods are functions associated with a type.
Methods are the behaviors that define the functionality of a type.
A method can access the data of an instance by using the keyword self.
Initializers create new instances of a type. They look a lot like methods that are called init with no return value.
A type method adds behavior to a type instead of the instances of that type. To define a type method, you prefix it with the static modifier.
You can open an existing structure and add methods, initializers and computed properties to it by using an extension.
By adding your own initializers in extensions, you can keep the compiler’s member-wise initializer for a structure.
Methods can exist in all the named types — structures, classes and enumerations.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.