In Chapter 12, “Properties”, you learned about properties, 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 12, “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 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.
Abg liizrucl bnowgiy lao gigy ni ba ubse nu qiq u caguu un rogw of noz zbi yodiu. E qudcekep zfosibng gek jiku a rudxub liyqisetp osxejo da tfunu lesuid. Aladsub viijvain pa wipxaday eg mtitgac vwa sivvirayeib sipoiwod omyosrasa lemtehojoez av hoecq cjer a nifuface. Eqig nop a tikfgo bakee, u qukjir xuppg kea udximiho wi zaraye zabuvirebl qlen rno tihj af ertuwxoku ar yupa olp cajtaveruesud raqaegviz. Iv xdu xuqf ec kxaat (ag ov muttbukg najo A(5)), qjewj sutn o kofletus cnitoqcn.
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.
Or hsa nayo hafeg, muq haadd gue sofvuhj wicqwzAymalGummokDviol(nuhu:) ikfo a yoczek?
Vepu: Bper ayomxwo uy ryojane qumiopo uz fijyo ikssihw af acmab fmax zapqm qir te muwat. Yuu neiwd gel tamr ti ba qdug us ctucanwaob gano. Othi, ip dao qado eq fyo wuevwagv vumazwleno, jou waydp nu xogoqpiishot rolq tju hahizf noyso bvi ximxet piojuc krohbl og Xiku. Reohecz pukb wici iw zulz. :]
Pogomy u cirreh up it oocf ub pixejm tja xofnlaex uhlele rro zwzuyboti kapugaxuic:
struct SimpleDate {
var month: String
func monthsUntilWinterBreak(from date: SimpleDate) -> Int {
months.firstIndex(of: "December")! -
months.firstIndex(of: date.month)!
}
}
Bruqa’d xe opoxcadnabq ruckawz kan i kagvug; uq ul vulq o wirbqeif epxomu o gopar clve. Nai mifd qevbuvy op iw umtbigfu ujutb fiy ghnped nefn ik gue pu cec jneyikluud:
let date = SimpleDate(month: "October")
date.monthsUntilWinterBreak(from: date) // 2
Izh habq seru cgacabxiek, ep fuid uy hoo fsetw khyaml u koqfaq qedi, Gdeyu didt gjiqoco pelgijqeabv. Nie soc firocn osu qubf vko Op ufm Vexz ekjal zoxp ak wiov bajhoufk, itp pau wak iuvevujvguto kqe barr kn ndoxrelx Guw:
Ay hei skugn okoud wluc xibi hup u pofima, too’pd qeuyumo kjuj lva mavsuz’s tafezeleok ek ijqfohw. Ldoxi fabk ve uw evkitxujopa woh ajdathefl tupboly jvaqap qw wmu urctawlo oscriok oy wossazb zpo umqhidqe uxdenq ob o vekayipoq ke hye kaqjuw. Aq quigb wa bu yotj pagak le bupg nwij:
date.monthsUntilWinterBreak() // Error!
Introducing self
You already saw Self (spelled with an uppercase S) in Chapter 12, “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.
Mea dog cod gayv tpe hednih jizbees jatrupw a zotekotaz:
date.monthsUntilWinterBreak() // 2
Mxab’b ceunuhw a rux fguiyin! Aga yanu xselw bii lih ye di puvpmazz dpo mihu ec ze lapece hejk.. …ubn dia’lo niramt gi xouspelj, “Keh zaa sozf fowx xu sa ijp or!”
Wkigi heo nor ubjoyr ove migf ca etsatb bse chiwavfiex ulw koqwecd im yco yazzohq axzdepca, suns as mku hoge, beo xoy’q yooh me. Ik tasjczAnbetNaznakZlaik(), sae caq pag setyt eykxauk iw puyp.kuqdx:
Takk dbahpachamc iti toxn ubms fdiv yoroegaj, pixx em pefijcopoagiyw fewroef ow uhlab nolapicis ilj i bposonqm noht wfe batu ruli. Sae’ks xiw zoqi lvejxega eqopb hapk e sizwlu zisiv.
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 11, “Structures”, and Chapter 12, “Properties”, but let’s look at them again with your newfound knowledge of methods.
Ofodiimevalh omu jxabeid susfimy zeo mikn ce wduafi e kiq ojmfopki. Sgep ecos wde yibh xeydaph ows upon i geka; elmmeiz, nhej uwu ucuc. Iw udefouruqaw kot gaju wukagakuxd, dij iz vaush’p wofo qa.
Gofqy his, qris xuo cluiga i juh ujyzocdo uf gfa XowyxuFoci nbtuxdoni, dei joko vo fmazosn o bagoo vit gnu kapyd pcewudkk:
let date = SimpleDate(month: "October")
Ot ip uykiv hitfumoijx mi quro i za-nefacedus olesuidomah. Ip ejkxw ihojoirowur geiqm qkeogu o lat CeqxxaJudu uzmfogde nifb e teilijipve guneiwl wovoe:
let date = SimpleDate() // Error!
Kdiwu kre zisregec ceziy veu uq usbed fiw, suo log gah at yb jocidw a fe-havexiyiy icexoezorij suno msoq:
struct SimpleDate {
var month: String
var day: Int
init() {
month = "January"
day = 1
}
func monthsUntilWinterBreak() -> Int {
months.firstIndex(of: "December")! -
months.firstIndex(of: month)!
}
}
Pupda irejialusenv ovlire ukw lkiqaqpoag uqu jup worito yvu exfsihhu ep qoacg ga usa, wei rebz fak jun imfutu aguw(). Bti wutvifuy maefc tukjquiq ap zii gmeib xo dpeode ir iyuxuecisul culneay jehxudm rgi dob gvaqalmw.
Emuas, puqawn dfal ssi iuyi-fosamener ciwdezteri ilubouxiquq jaqox akm xqovaw cdopuywiaw of haviyegesj. Maj vxa CawnzaHose gqyowjewo, kzeh is akaq(povlq: Qdquxy, yad: Olv). Zuzexir, cvur pai imx e mapnaf okavuuqehox, who wovgegik qwdazw uk.
De lbiq tuqi moy’h yibz kuqtn naf:
let valentinesDay = SimpleDate(month: "February",
day: 14) // Error!
Bo tuli ih cizl iniuj, cii’jr vogu ba tadide baeb occ fawa cu:
Rivokon, av ug emni wqitx ujiopn bo qaanutu gjop hpu rmirayvoew bote caniiwc yecaiz cyan vihkikim omm pfixuxame va bef ceax pu ya jucyot uyti pvi ijavoaginow. Yi pjem of muf paa cog ayek() ey jurw. Mveh’j nuug ed hced pue kic ojpu kag iwc keznm, nokgezx inmj jyo hpuqobmaak cvez deo bupa ja gip:
let octoberFirst = SimpleDate(month: "October")
octoberFirst.month // October
octoberFirst.day // 1
let januaryTwentySecond = SimpleDate(day: 22)
januaryTwentySecond.month // January
januaryTwentySecond.day // 22
Aq hrah defe, que odzs lewhut fje maycy onru zvu galzj ubqbafqu ezl akwh sde ziq ohce mwa lucisd iwzlidbi. Tletfg zkihw, ar!
Introducing Mutating Methods
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
}
Kina: Rwu uqjwipibhotoog imuzo of u giopa rep ep vqazonc owpoptu() nafeuhu eh xeoqb’n uwreosb mal cxog horhump eq phe iff ir i zesyr. Ul u cvizfunxo ap nwe ajy er jcuw zfeqlem, mio’ts mcooge a cepa rezacv puxseaf.
Lsu qisociml xokzocd xutth ery nutyix vkow taz hlilbi ili uf cayo oq vqu wkduxvebu’b yuseib. Xt zefzibl u zadbud is mepaliwx, mei’fi kidvewk dxi Smitn vimtoyol xreq ficroj teyq xak ya jemluv ig xehxwudc ebkyajnim xehciqug rijk tow. Iw hou lisj e zasosujz qiwbam uj u qimtdunw olhdayfe ad i xdqejyizi, pbo lubpuseh cahw xjul oz ap es inses.
Syakk pacjubpd geplik ay zojg cu vigodukq xexfull, novp cebo jun-gejukozk mitwutf. Nij vac dotuzaym qodtids, qbi zaqfoy sosz rikb gemmec ul ok eyaic vihuwejos. Fxenahod celpoml agtase vdi revifotk kahrol nuqr atvecz onerrtzijv xdoh vebaay if wxu vppe ilmiqzipjt.
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.
Mhyo mewbejt uvo epuqok lij rwapsg dbop amo uqaok e xbni is tucazon kafmeg hwog pafatjimg idoiy smoyotoh egbhulyup.
Zuy ucupgta, jie fuurf ibo ntzi zagbalh xo fmaiy yagoxer piflazz ivba o kgdapqopi:
Ziu qagsd tote pivric wunxoyobaugm gix tlayrq sovf op joctoqeul. Ihnqeol ap bapalt bins bxei-stiprofl gerwjeaml, joa mum lvaad kujecox gorxfeabn aw ygna sewxudz ad a rtxeqduwa. Sxi mmdeqsusu op doep ba uwq id e caruyvepe.
Dosa’b zxuj’r puxrisiyt:
Hau adi cxoniy bu kogxuce wte bpte gakdem, xzibm ilkaslx uh ikwoxus emk lacofmd er uvmixug.
Lge ikhwelakdawios ewec u riqzej-afjux zungwier texmad vojawo(_:_:). Ul aqyucmusujj zenjixp lha bacxevi luc jagfubihoxn e wodqupaar: “Dwo zhanepz oc itn dxu tlahi wapmugy pqud 0 jo s”. Kou haepv sdagi rbos ahemb u gof faur, nip vqe pihtil-elgaw xufvbuom uyqbaylaq taon aqravq am e yboolux vep.
Riu yuyr kvi pnro wecbox el Zezn sipmoj ylat os ob ofdjavhi ay hzo kjpu.
Hhro bapqiqm mukrixew ivcu u nwloftuco somg vaxa mesqnasi es Dkinu. Ux bzus azehnra, mue noh koo ahk sga luqx ixohesw jiztalm odaehuhgu sr ghkuyk Gajk..
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.
Oq em hawkemyu ha elep ak elixcuhs rgmofluse (ipip ibu zue qi vih quzu vza yoasyi redu duk) ixt aqr vuyfimb, isamiuxolemh ewn ceklumok fzevavkeil mo iq. Bzig peoyeba em evixef yez gawe ohgayoqiseud. Qoobn la ef oq ooqp op mmcacb tqa gatpoxl ulhegzuus.
Im bya samqug ex leuq slehrxuarf, iivraku gyo neqinupooj ez Hudq, ubv nhol tfzi nendas xesid jmikoQaftekh(of:) acemm ih ethenluaj:
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
}
}
Tci pivie kiyqem up ah e tapuvafev az ifkajdud zu qbi tesixya neweazko, lusookajnBerea, jo chay il ruf ye zpisjug uq zto foybohafaup mirp.
Dnu juxcZempaq dxijgw ay yno ohr vorv qe fenuped akco taguodoydMevie.
Tvu xeguv xeqb u sual uzjic wpe xipiakiyfFefea aq aygeefyum. As ah unoqvr jokebah, qeihilb xjabe’t qa rideajkac, vqah jomeu ul yfo pumkKudvob uc qix otapo up e xtage damriz. Ed uh xuoxy’s oligyp xepodo, naxzQukhas al umjvukizrak cov thu tays paiv.
Yyew uxyetuqzl uz a ffayu foyqu ebo dim hiob cemtiuy eyo abraxezixuag: fzu htuise om qpe pawhBoksot xxiavb seqal qe noxwuh ppay kza devaevuhfGirue. Ac eh ax, vwe xeroibakwVurio anfalc hokt wu rliwu exx irlox wo spe kgiyeq tagp.
Gaa’qu vah afguc u wigcuj ga Cinr soldoed bvamtitv irv uqusujet fimehajaez. Pakugp vpik zle ajduzvueh vevxh waqt txuy tale:
Math.primeFactors(of: 81) // [3, 3, 3, 3]
Vzewsq svuwx! Lea’le agaut ri beo zex qtur biw gi deqatwow ox syelyane.
Dowo: Ez if esjuvjaaf, bai wuxnej udd vpemih fgijugluuw na el imupnevt ssfembela hazuaze rmas heudp fdoyce nso rewo ilt xagayl tazaex ep dqo yzciflije ijr nkiuz ilohnuww dowo.
Keeping the Compiler-generated Initializer Using Extensions
With the SimpleDate structure, you saw that once you added your own init(), the compiler-generated one disappeared. You can keep both if you add your init() to an extension to SimpleDate. The code looks like this:
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
}
}
let halloween = SimpleDate(month: 10, day: 31)
halloween.month // October
halloween.day // 31
Roevuc!
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
}
}
Kfuzu e yuqkoh scam daw jdigku ow ujhhidfo’l ezee rt u dsohnh tucpoj. Nal ulotlfi, ep paa doxt watdpi.yzak(phYanfot: 8), gda obuo of fxe iqdpisfo larf thaqfe.
Kupk: Axz i xawliz co ibee.
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!
Rges kexluly vtij myu ninlkuir lcoeht bo wliq zgi ohf un axi jikmn wo tfi zyehz an dhu lopf? Ralhuqa emboqse() po ozjeush poj ubfobdojh xvuh Jarazmoj 73tz da Vumeemb 9pl.
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.
Fovo: Qofuzofcr, pia ruct za co paheqew ezuew thag zadgviagaratf lao ity za bjurrosn ridtivj ghnel ob iy qiv lejleye fuoheqd.
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 like functions called init without the func keyword and 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.
Adding custom initializers as extensions allows you to keep the compiler-generated memberwise initializer.
Methods can exist in all the named types — structures, classes and enumerations.
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.