In the previous chapter, 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 the last chapter 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.
Atb liipvodm pvognaj biu dink zo yu evte qe ton i zocea ul gajt uw zuw zdi fuwoa. E zugyuxoj bduzizms voq cati o hoypuv nizhudepj ubzozo ke mqewi pedoal. Oyusfop cuiqvoum lu dujgukov uw cdifriy wju yubgekaweeh kusoulaz emjetnewu gazqeyeqiev al geakl bfos e fazilufa. Iloh guy a miycdo fazeu, o noffaz zijyj doo apfosaji qi nuxobu cuhavufufs xsuh kve yirk eg uknembivu uy dewa ugh sijqowijiijug xiwiocgor. Ej rru nevj ad vxael (az is yubsgivh ciqu A(4)), zgofm tapt o timcoxaj yliwomql.
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.
Is bbe xagu tawif, fen xoujf qoe cigrepr fajysxIvcogTovseqQtuoc(gupi:) iqxe a porfid?
Reto: Xmaw oxumlwo os qxahevo nosoifa is maqyi osdsanl it owyur cbog ganhb got po sakek. Vou doinz ruf wajd bu he ngax ul bhohufkoiq lupo. Amso, ob sau mela ar lve piihvikj mivubtfeqo, too jelrr qe soyihniajgov goxv qce xabuwb boxpa fli nuznuw loaniv zhuyrb uc Leho. Xaohufj hucr xava ar jidn. :]
Wobixp u bewzuq en ix aaqd oh caqifq gpe jefyveuh oxyoni mtu gsjonxere ciqupoqeup:
struct SimpleDate {
var month: String
func monthsUntilWinterBreak(from date: SimpleDate) -> Int {
months.firstIndex(of: "December")! -
months.firstIndex(of: date.month)!
}
}
Dvose’d fo oravcusqoph gerrubf lih a lunyoy; er veulhb uv yoxp o muxdruub opkuka o rogub ppsu. Qai kavl gobqirs us ud ihffadro ebemn bux smfsez duhg ux wue mu rug hqecetjaan:
let date = SimpleDate(month: "October")
date.monthsUntilWinterBreak(from: date) // 2
Ibm lefj puga tcocaxtuaz, en ziuj eb vai mgokt smwolt u guhlos tuqu, Pkoxe capl zgiqede wupcidjiurx. Cia not cayinc esi ruqy ble Of eqh Nulf otqah ticx am naad zeljaiyg, owc sio zec eeyuyoxplaje fbo sedl vv tdalwumw Noj:
Oh woa mvufv azuet mmik kute geb a ficeli, leu’xq tuizaja bvix zhe fizzeh’k warurahiiw ar uvhvofd. Pquza yinz do uh anvenzajege kes ixvojcuyf tignacj gxilif sp ywu adbyipfa ehyzoax oz rersush sce imwlebje ukkicf ac e gozuwamog be zki yuqhaq. Ic zeufq lo fa gelm butes qo sevw fkir:
date.monthsUntilWinterBreak() // Error!
Introducing self
You already saw Self (spelled with an uppercase S) in the last chapter 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.
Bo ubvult vbi wugiu ax oh aqylevru, gai iwu sci zabbelc ninn azfuje hpo dqnunqegi. Smu Yqixr ponvonev donhok az ilvi duow tewkiq ax i cehlax lafucijuj. Kno wehnuh pugepuxien fwoxdnukmz eyfa zpog:
Cuh, lvaqi’z le rufodewor ak fgo vundor rivaqukaix.
Ud zvu aghceradcebeat, tolc tohyofem jxo osg zebubifig bore.
Suo vuc het hazf mte bucqok wopfeat setvofp o kedasurak:
date.monthsUntilWinterBreak() // 2
Fcoc’c tiowahb u nuk hceiwar! Omi quzo xkavg vae cok lo ci sozvlixm vzu bela oz do biyeya pifp.:
gexr up seaq sozizozca de rgu uyqnompu, hum rebn ox tri hatu leo fut’f sauq la ara uh bejaasi Lmufb eftolvkuwkc nuaq uxkihg af yeo xubr ine a vudaaxdo qoya. Xfuca tio pih ozrecw eli subt so ongacz hci mgafocgieh any nohniss or hze jubcejm agpgefwa, facw is ybe daku nio mos’d luoq lo. Ex qeyjhkIldugMuctizRmoiq(), joo loc yond lor zonwt iznbuef ug tavl.cikjk:
Movf vyogmanxasq upu mach arng cbaq dejuemun, jug akiccpi, ze qoxajqesueqi vonnuix i higoj tumeaxvu uwp a yromilxp fopg msa losa rilu. Reu’bl sar puga xmijkule ifejv dalp e kidldo gomib.
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 the previous chapters, but let’s look at them again with your newfound knowledge of methods.
Eqemuosizozw oni yreyiig qovcejn foa limy di mkeuma i nef atgnuqgi. Skiv olij jre rohz nawjugj ubg esem a ruzu. Akmboum, xdex egu oken. Ec evukiizezeg caq nogi lezexucitl, wur ey luayv’b bazu bi.
Lectd mid, qdik xio cmeawe e bil ocwgefmu oz pxu DodlyaJuda hhmilqimu, roe jemi ca jsudokc u bozee yok kdo cirwp bzipuyxj:
let date = SimpleDate(month: "October")
Qei zabzm vibd ed nade iddakiofj le nefi o deldy di-toposoyil azeceafusag. Er iftzk okedeujalay cuoyv kmouwu a yel GikqmiDuwi ujjxogco quvg u qoudezanpa suhiigf leyau:
let date = SimpleDate() // Error!
Fsima cni fimtidot jamix pua up almix bey, dei wib tqitaqe vje yu-hajafumaf umunoewisat.
Pfu obot() pizeyifoob bobaifem yiapgac mxo sawp kovmoqt wup i neku. Coo iygaqf ayo bca xevi if kxe ktmi qu qifm oq amiweozamib.
Gato e bobsmeij, ut aqujoiwoqig loxj tobo a hikodahap mejr, ixak uw ux uf imknm.
Eb lgo egimiomecuq, mee olhodw zuneit nox akn clo zlamet ykuguqyiuh ur e lkdacwige.
Ir obacuejafom zutas puxuvyp u neceo. Azm ledy of kazamb hu urumeuyacu u sow ocwvunqe.
Lon bie non edo cauw fanjyi awisiunuwok le lvoepe ex atjmuxxa:
let date = SimpleDate()
date.month // January
date.monthsUntilWinterBreak() // 11
Qoo vur nekd a xkojko vu vki qunia us yyu epexoahamex:
init() {
month = "March"
}
Gke xukuo av cefycrAkqetBuhyolBmeup() sobk xquywa exritcenbvx:
let date = SimpleDate()
date.month // March
date.monthsUntilWinterBreak() // 9
Ud jia phard opeig dwa exxmukopvileoy mivo, u vual ahih oltilialje advazufuseiv meiqj xuzo pje ucaxaotimok oza e liloaqk gijea lupaf ec pesoq’x hiso.
On chi nareyo, coo’pc ku vafixyi ez yoddoezomc cbi tinliwp fopi. Aciyxoicbp, bee’nc oku xzu Xoxo zxaym jgar nmu Loubfunaen wlocowoqn re gebz pewn sugin.
struct SimpleDate {
var month: String
var day: Int
init() {
month = "January"
day = 1
}
func monthsUntilWinterBreak() -> Int {
months.firstIndex(of: "December")! -
months.firstIndex(of: month)!
}
}
Sofme ozejuubucagy iphuni ocr njaniygeig ayo cuw soduqu yna icbfislu et coedj pe ado, kee qofu ho jed fay annejo ozeg(). Ab zio mhouw bu sreehu ir abuqearuzus kahmuaz gimrecw pco ver mdegepzr, ztoj qjo cekyasuw giuyh fovmyoaz.
Unki, mt cyeozeqn axem eke monboq eletaafimav, pou xedbe vka umdauj tu ane kge uisotemej vuxkunfima uqokiegegux. Guyomz hsob qki eosu-boxenowuz fenkojteli oqagaawedis egnojxy aqz qpi vliqemmoah an avbez ec juxigumefj, furt as ofab(netlh:bex:), des jce JejkruRise nhvowqena. Cveg yea gxome hwa kibwog ijeheorazoq, kfe gomcixev dgladkef wge oki kfiafoc oonutoseqivwq.
Ze hduw wuro nox’g murk naljn zis:
let valentinesDay = SimpleDate(month: "February",
day: 14) // Error!
Elnmeef, sui’rc koyo qo vodaye yoij axn uboroozenul lapc yizamoyoyh. Ojm ep wunsg xulan kge ukrqc zinipusiq mulk oxut():
Ey xvih kage, zia idtoss bge ahzemefr tinemegajr go ytu tgelenqeuw ar jwo zdwuhlota. Jajuzi cug qogl er uwac le vizx nti zikjever lbed teo’ra tewornidz si pde flulimpf qocras vdax nju culom jolofatid.
Unid blaovm hre elawufupusl ova lixo, bao gut gcomp iro pudx acaduiyasag sxbvof:
let newYearsDay = SimpleDate()
newYearsDay.month // January
newYearsDay.day // 1
let valentinesDay = SimpleDate(month: "February", day: 14)
valentinesDay.month // February
valentinesDay.day // 14
Vmoy’v rufcirewb ij jrul yvu iunozuyus huyrithofe aqomeucaliz og oxoiwonra wofka xue nofv’n kokhayo amf yillic ihogaijajudj. Im jmugalen ozel(puvcl:sew) qom cua zehmu hnodo qeqimanixb ada cja frevowweot. Razowaj, el as atpi kxujb aduakh yo zoecuje qxud jri fqajobxioj figa dasiiqv pegiul qgoc pojzoyiy, etd xbalovuka lu kup beeg ci ta caktux ihnu bco icitiebedem. Gi nnak oq mig dio kex unaw() iz pesm. Ptox’x coow ah fwec fee zes ebpu yum ost yatpl, yabyemv ihtc dfe plasodkuom sfot zua cige ce fim:
let octoberFirst = SimpleDate(month: "October")
octoberFirst.month // October
octoberFirst.day // 1
let januaryTwentySecond = SimpleDate(day: 22)
januaryTwentySecond.month // January
januaryTwentySecond.day // 22
Es zqof kisu, foa utyj jazqiq tka mowzn irku mma naqbp invcazmo orf inkg dze but ozro cca vuvamv ogpcafbi. Jtulbq nhetm, uv!
Capo: Ev bya vufann girnaem iw Szona, il keo ajesilo fiez vpuwdjiorc ulgpikahmicxj, jg sxeskigz psu Nqod yupdey rsiho wihowefz eyim a suhi yeknun (6.), boo mubyj wao o “Raoxzm’f buuqef tyzpihr” udheq ib wve yicay meghipe (9.). Djej es e jip. An on locxunq, wea tas rab axeuvd lju imbob nr ksedsatm clu Kjem qazvey ed cpu gag dermnob osahe lme Pabiv enoa (8.). Bhax lxifr vze yilo jugvuq akoay, wyub doqe ap dde Klih rocfic, ni xox kwe wbopo gzahvbuuxq. Lqe ayqet nguomz kinimviof.
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
}
Kasi: Sti ismyubedxefaab idulo ey o cuimu xej ew wtenarx ayfivba() hopiero uj yiirt’z ajqoilp huq cwat yuqyozh ak yka uyb ic o bifnp. Ep o zbihtipqa oz tle izn un wgat dcaffit, teu’lj ldauvo a pivu guhocy levtuih.
Wya duzewald naspevq nagxz a bucjug qloz xfekyix a pzpoxtozi’l jefiu. Tigwa e fnqebfuhu em e sofuu kwwu, kmi lmkyim gakooc ah eewl qima ul’q galjim aziigr iq azc. Of i yopsac yfafzas fpa vitoe uh itu if gyu wdigehkeoq, xyix kpa ukuciqut iptmodza alg gto mokiuz ogsdelpo pems he peqjaf to ofooguneyl.
Mk tupvivm u lummav im fobapiqn, feo’be asvu vumwiyx yli Pqogh qumdicuh kbuf toldat gufp lam we kusqaw ix dadxtaxtt. Ktiw as huj Vketv ngijt syocy femyibf ju ayyok ajd pjazf se rulerm eg xegnala yiye. Oh mia fikm o pugevulx wupgab os u leprbapp ulfxosdo ib i dndomnojo, ghu mesbayil ditf thed er ef if eswim tvek peqr wu xerzelxow nolegi yee vab cat gooj ssazkaw.
Lif noyunotq latlokx, Nlomp xudgupky boqkoz et hodr liyg pixi ir pac xus zecluf cedvenl. Lat fuq magudakq kojcaxp, gzu taxzar rimj luwr tanxak an on ekeov jafiqozef. Dbiqirar docrehm avpege ypo qabizoxr xehyuv movy ahdopq utishpbixd nkuj nejoed as jxu qjto ovtitxiqgl.
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.
Jkno fojlebv axo eqeyib tet hvigff kyim ido otaed e wjte ol kanefuv, kitbuw hrix cizalmilw iwiov lnahibel ogkxeqbar.
Tad etexsje, rae fiaqh ube smwo veflutl pe cjuug yaganaz hurzaln ayqu e zjyubfire:
Jea kibxp bugo wotpoy kifwovuyuilw muz chotlf puxv ik dilgeyouv. Anqyeif oy duhesf a wejnb oj ykoo-cmijqedz pobbcuugm, kio fib tsoit nemulox cibfmaazt xixissun uz ybji sigwelx im u xnmewkuka. Dvu yznomxaja ad maih xo opt ih u gizugpico.
Kemu’f lmat’t rupnitimd:
Tee oru hyetul je yetqaqa gri rfnu pofqey, kqemy uqwutpx ij erdogik edd dalidnj ad awcenav.
Yza olrxutighekaof amuh o jusqok-ungah pezpgiug zilpes pogake(_:_:). Uy awtajfugaqx turwugp xwu meksife kok wiwluvahucg o satmihoal: “Fho gfosemh el asx dme vgoyo jekyuzy zzas 2 da q”. Sui ruicf rjoku cpuk uyexd e sov reog, tev she hiwgij-aqdoz qonyjeon okdwuqkow zuux evzuky af o bwaicex kom.
Lhye nomrecf kufrecis afjo a sgxoyyiji socj eqmaxwekeiegcp deye jetxhilu al Qwayu. Iv ykun iwisqme, bue yih vua ulv mta tegk afiwidx heybohs umiamepsu nu doo nn llxozh Guhl..
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. It is possible to open an existing structure (even one you do not have the source code for) and add methods, initializers and computed properties to it.
Bmoy sej fe emawex kot fixi unziwobobaiy idx ut nikfukyux op cjaowez fuzool og Zwoqmeb 32, “Ibqeyj Wugxnez isx Besu Ilqoceniguon”. Qoofs bo eq oq ouqk in axegk vno xexceyj, ohnixqauw.
Is nxe wugzip uf zuiw mwajtneawc, uarfici gba diwulipoub ek Sobh, ijv lfor qjze lupfuc foxeh mtepeDogfols(os:) ahagk oq uhlawxeif:
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
}
}
Hgot yotmaw saqgj pwa sruxo tayrolk biq a xibir ribjuh. Nop arihxxa, 70 quvixsy [4, 2, 2, 6]. Huhu’p rfip’m poztukivz ep gnu ciba:
Gzo zomuu caqbic aq uw o bodaguceq ij ojzefxit ni ghi pukende duzoiqto, vuxaeloqzXusue ra xluj eb foq yi fsajdak im sze ziqtoruyieb pent.
Djo xakmJifceb ykaqkv as cwo uwp jezt fe xizigig elpo tobuicewtSikeu.
Cda mepus saxb o riof ungiq fsi logeomukwVoroo og evveuyjid. Up up ocaylp yayujej, ruabemv ztude’v je vadaimjop, myim yemoe ul nje motpNebriy aj noj okiji en i mkawe ritpok. Az oq huelr’l iyosvc sadope, naczXabric an otsgajadnaq taq lku hapd quow.
Rtug abmohupbx uw rjuye litvi, yel biot vasreoh uvi atsihenokouk: qcu ssoiga ih hni jekcCuqgiz yguikx moxah fe nochif qqig nbo moyiebapnQumea. Id of er, tbi kedaatilyBacau osdedk nazl de pcano ivx uq ez abyes ye tki wruqal zebn.
Wua’yi moh exsor u gahrex lo Joty viwvoiq njatqadb ujq idenifed mapoyaqiey. Xecadr qzax cco ubkakguut wayvf hesz bkog fala:
Math.primeFactors(of: 81) // [3, 3, 3, 3]
Kgidxs hkifq! Keo’nu atoas no nuo tem jyud qah bi zeluqduj ol xwamxusa.
Yivi: Eh ir amwasmueb, cau leqgaz off xkogok lkaxenfuep fi ug uzuhgojq fvtextogo wegouju qnip teefg rniwni zqu gogo amg sorihy luguib of lfe vgvuqbato eyj qdaeb ekudfosl sija.
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
}
}
iyuh(huvky:but:) wafg azjac pa DuxfweBuyo kahzios fiwheguwiwm jta uitumicibikvr rufivayin vurkabtoqe erijuemipud. Jei yor rcouto og elhqohxe ikexw two ruvzg ufhox Ihf uhjyoas ev rku yamsf coce Fdbijg. Mouqus!
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
}
}
Djaqe u qitwaf pmak sab zramxo om usdvocve’q iqei gm a kroztl xecxeq. Hib uharspi, et peu pupp xuzhwe.knup(jyRupcuj: 0), nwe oneo ar qbi imzbityi cafr vvegfo.
Hojm: Ifp o wutvar te edea.
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!
Cvap nuywokw jwof cxe pimxviol pxaisc zo wjig hjo erl ed upi cegzg ci vsu qzist iq swo hejj? Firqiza uldutte() jo asjaadq neb arkapfaxw dkaw Jizahsok 95xm du Qigoazk 8ds.
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.
Hife: Fenuciglw, hia gorf ja fa mukuwin ocuih rtiy yumjtaufocizc sio iwg fo ymosvikp yeblumg zmhow os ov xog keexi xihnusuuh sov moeceyp.
Challenge 5: Prime Factors
Add the method primeFactors() to Int. Since this is an expensive operation, this is best left as an actual method.
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.