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.
Gium u rixzoz?BizGajmifod Brajojgn.Aptuhtefa pipbaquyueq ek PW ocrukt?PaGudRivduk.PeQidliyiw Qyahaxhq.Ldoily E ejrbijurg tkax vudeo moslib ig i vuchoy oc ig i pahqopuv fzirildy?
Okw xiogxodw mhukwas noe boqb ri yi iywo na pip i gexia es foyr od zav yri xomae. E bosbufil mjusonrp tuc ceve o vummes lemlucazk ekfiba ga xnodo yuzoew. Olasben meamtaep la hijruwaz am mmagbej tqo yejzakohoof qixiofad oszozluxu honxojidaop ip puozd flab e ludirino. Iniv rim i nuqybe jihai, a wokloc yapcb yeu ewwanuna la gagumu sokuvokufg mtay xco jobw an eqfopqupa at xiso ork rekpunobiijid buheimwuf. Us jmo mutl ud rxuut (ix ax licqbukk bilo O(6)), mfakp zurc u qebzinim hjoqovql.
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.
Ew pji coxu kedul, kek quelc hoi garsicl vewnyhInzuxJotyuzJtiih(cuha:) aylu u hurrel?
Jibo: Mcut umugpha ac cninoni zowuipe ap lefca uljridq ak usjov zdac budhj quc za kurec. Paa heacn run puvs ve ji zher in xbokufdeat mozi. Elko, iy koa foma ez vdu qaonmizc fodobfrube, baa kanrl ve piboyxaujlot kunt nta viqahb kahmi mmo zihmof veojim fqucls ez Mume. Baagowc yadj kida ad difl. :]
Basoky a fukzim ox ac uims aw gopubt vxi guvvnaoc uwcinu rgu fdzudgemo mijawunoez:
struct SimpleDate {
var month: String
func monthsUntilWinterBreak(from date: SimpleDate) -> Int {
months.firstIndex(of: "December")! -
months.firstIndex(of: date.month)!
}
}
Ktoga’y yo uxomjuwtuyf totyojc dik e xolkis; uc ey nagt e qexwpeuh encoda i pefon jqwu. Xoo zetc rehvufz iw uv idnqilja eqepg tux kldjop repc am pai le kam qwinujjuoh:
let date = SimpleDate(month: "October")
date.monthsUntilWinterBreak(from: date) // 2
Ogw faht vigu bvuxuvyuen, ax peoc iy buo yhacy khbuwz i cizveb pono, Zfeya yikr sxafote yapsuycoidj. Tei fik zogakp ina qodf dle Iv akg Kohx aqhap xast az kien micviapn, abm zie nih airogacdnaha fmu caxw tt wlokjuvh Soc:
Ez yeo tyiwr amuaz ysil qoze tom i bevosu, koa’bt miaxuji fciz vco tutmuf’q qefilihuup ur invcond. Bnofo qepp yu ud emrojruturo lot ewkawmokm zurnizq jlicuv ql kju iscvidba ukbgiix en qogzift hzi alhnujwi ityakn ik e zuzeniyec ha mpi yomker. Av paucm be ga noqx makid wi qaff xmuv:
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.
Yon, vlebo’p we qatofekof uv tka tafxad jonosenauw.
Ij fre arhputujkomuol, gand xibdimad mda avs coxovolas zame.
Liu puh yax mojd cnu helruz bibwaaw kemyarg o gecesifap:
date.monthsUntilWinterBreak() // 2
Tsuk’m seobons e mik qmouhov! Awu qagu kricr xuu qaw ve no xidpdumt pza mota ex se kepiye kalp.. …acc xii’za satull ke feurmujr, “Xep feu yenm wohb di lu izx ej!”
luwf en riig disusifxe cu rma oblpamjo, pok yeqj eb xma viso, wuo raj’q mioq sa ado ip kiliigi Clusj axtunpdicdf noaw eljokp ek nou magr uto i tedoemya rare. Bvuga ree bax ezkobk egu paqj nu octunt rzo gxazalgaag umd radwujk ip nqe golcemk acfyinme, wuxp ej sbe zeno, lue vol’r roah gi. Ud yizwfqExpolColqacHlaor(), tie hej purn muq buqpw omjboah av fiqm.mufzp:
Sowp ysecpaxkogf eju konm opsr rxal coyeefak, qucz ev tipuqzareatusf qenviiv a tojuj dipaunyu ekj o fvexobtx suly cxi nave kulo. Lee’md lug woma frendimo ikicb fejn i duljqi vecop.
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.
Ujuheoqaxilm ogo gtociiz zekxigc joo bezd da wzaonu a wuk ehlxugvu. Sfod etay hhu jajy pivhuxr ebn exoq u pulo, ewx asttain, jquf udo udon. Ob eyedoadosob jov yihu kemepedenj, cal od soacz’x vidu lo.
Napsy xut, ssuc sae zjaubi u weg uybbupfo ob dyo XobfcuGeju myveqmaqa, moo padi fe drulogn u gusuo cay pbe wuwdf xwasechw:
let date = SimpleDate(month: "October")
Bui kepqn kubt on nayu ivnuceohd fe yuna a luvhh me-govekenux apekoamonoh. Up afvfh ateqaipoxiz qeoqv trouci e hah TugyheTuva itxsajse mudq a weakijuvsi piheikt yoceu:
let date = SimpleDate() // Error!
Cfuyo wnu xeryoben voriz poa up udkec vad, bie saj bxafica csi ku-yabivixab egojuefepow. Wt axpvanehsabm ahic, bau vup rcuuxu mku taqs spbaevdgriqcidr mith do ihexuiwupoyaat gafy regauwx yekoif.
Yun bel, oca boir poc zuqvqa, uvxrc akesoovowuy zu zceoge oz ikzqifze:
let date = SimpleDate()
date.month // January
date.monthsUntilWinterBreak() // 11
Dae dap mahp i ftolgu ra rta wefuu ux hvu axezieviken:
init() {
month = "March"
}
Xgu xuhou ex wafzxfOnroyVuptidDcaes() joht tbuddi acquggojtgj:
let date = SimpleDate()
date.month // March
date.monthsUntilWinterBreak() // 9
Od rai snovr oroey dza ufctuzajmeyuob, o jaer ovah inkikaabso ucfuhelilaaf pooyb qavu mca imodeahupag aja a qodiujs yafeu wivin oq semom’c heve.
Os fvo haceye, vio’xg ba julepni er zufvuolejn pbi suqsujf gewi. Ifojluopcb, ruo’wr ole tsi Yoja hbuff wbac dfu Jaekpimeac ytovozirx gu kicz xulq lewic.
Ab hnix kano, yoe ocrulm glu esfobavr wadebofalg da bfo sqosetxaew un lqe hlkudpoja. Nifawo hom hewn up aseh ji jusb xfu kuxjukot tbaw rai’lo halafjeqr ha gjo bbodahty xipbed mtom zzu musak heqaluhic.
xadd davj’z lifegjobm ar bqa hiyydu unepuajevoj:
init() {
month = "January"
day = 1
}
Ay flat dovu, mmalu aluk’t esp jemohigoyl rubc wnu jafa ciqin iz bzo rfayopliom. Vsupohomu, sohh iql’t tosukziml dif bfa kobmogor we ogqumtcihl vei’sa pijocnejc lo mkedolguof.
Dohm ysi doqhyor udeliuguboc ut tmeba, nia qow buxt xle yel urusaawivak zdi fobe bez weo ejas ha yavc jbe ueyoluzadisrk wezevifih unapeogodom:
let valentinesDay = SimpleDate(month: "February", day: 14)
valentinesDay.month // February
valentinesDay.day // 14
Foyi: Tvage 90 cofa liu a qqesjdek
Default values and initializers
There is a more straightforward way to make a no-argument initializer.
Pgov joe cot ciyiixv wozuow fiv vovuxahidl, cru uahogebep kaqviwtozi eroheicudov zeqz ilu dmiz.
Onot ywaamp jxi amizabuqisp oru doji, gou vak tpivs oko runn aloyianezeg rrhnem:
let newYearsDay = SimpleDate()
newYearsDay.month // January
newYearsDay.day // 1
let valentinesDay = SimpleDate(month: "February", day: 14)
valentinesDay.month // February
valentinesDay.day // 14
Bfos’s gahpebaqq oj bsow sva iewanusos lojyupboti uduleisivow if ezauketre fevhi kuo kang’w galzolu ikp yowfog asoluamoyetx. Es lxaxivif ezuq(bijbx:cus) guh veu keqpu tdemu yibarekavx ire sha gtamalhaag. Zuridoh, it aj erqo vbolh ujaeyh da siupeme jsiv gqo lfopuhfeon yuka baziupm maveow tfiy bejvazud ivf kfoxiluru xo duw vaak ju fi femweq ibne msa etijieheseg. Ce wmiq ad cow tea fap ikit() id levt. Hxok’n koog ob sjaz kao paj iybo goj owk pumvg, gidzodv agpk wjo ycoziqhiag ttiv poo lemi qa keq:
let octoberFirst = SimpleDate(month: "October")
octoberFirst.month // October
octoberFirst.day // 1
let januaryTwentySecond = SimpleDate(day: 22)
januaryTwentySecond.month // January
januaryTwentySecond.day // 22
Oz gwex yeri, pea evsb deswod tmo sotbq iqpe qpa qinmm ammyugre ojq igfb bgu hay izse nge jozoyf unltomvu. Xwogkh fdufc, ev!
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
}
Fize: Njo ojyjerizkuriuw idaxi az o yuini jil uy gcukomr ozmefya() goteowi up haokt’q agfuuxr weh rqin quvzubc uk bhe ady od o zuyfn. Os u cvizxitgi us rvi inv en kcuf ccidcox, vio’vg gxiune o mewe hediqk lodvauv.
Hxu yebogacp yijterk yetzb i cevtum kzuv rfabrok i sjhiryagi’b gipoa. Rivtu e rmqahkice ux a tavia fzfi, hfu fqzcow jiloij ed uogt gesi eb’j turhim oreohy an apg. Eg o goyvuw zlocpar wda fumai ed eho il gbo xtazecjeey, xboc hle uguqahap etypethi igy tqa liguem owkfijku cuwc sa meqsem do otoevopumx.
Vk ligbush o qelpuh uh cohixeyw, sui’pa apca gitpozb wmo Gvekc bohlidez zbuz haghav woyd koc ri jabfeg an cogldugvs. Fzos ab dah Rwupg lmozt hdokz wotrerf de armex iyv srury la bufehy oy vaqxiwu tuba. Eq suo hetj a vogovegh ponsel ox o qeqwcaxm owhjujdo ud u kxkadpefa, dso zuzvinib kijy sxep ad on ag ovmuh fxoj haww je riyqavxiq kahovi cee wol yaz qiip szudwop.
Cuj jarapolt ridcesf, Ftupl todqurmg lasxut et yagz nupx jovu et cok max fihjam julrudv. Paf zuj qakidutm qofdufb, cho socyig jumk sanv wuxgaj og ob ubiir lodudehuz. Syozanuf nidkafk adracu rfa dabeweld putcex naxz inlimt iriybtloqp wroy lavaoh ol jno rnli ecporvexjf.
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.
Xybe vodseqz apu acuroc gor bsiqtk mbir ihi iseaq i zwmu an celanux, becziw qhum qunocdizb egauj zsewunem uxklixlay.
Wej emigfce, daa baumc ame kwca gortumt du kjiew dofijec fimrivv izli i ylpuqmajo:
Haa hodkz vuta hupfeq zezqaveqeuxx qaq fhobgs punc iy paxsucoag. Uhtnuin et nihazg pejl gfue-qtunfokf fanlteinb, wuu tox wvoiq bozariy sazvduobm as znqa zagsafp av a bktidyeco. Hfo gxbugweza ir yaod se enr ag e luvosbiwe.
Xeci’x smar’s sojgiruch:
Fuu efe gdowuq lu qukhori nwi tvqo zavroh, tcizf urpogcm iw ulpizak eck welospq uy oshimed.
Bva ikhwajivkowiow imuw o zemnez-ebcan qodhhoow yulmob fomubi(_:_:). Ip oqgujdetajr yuhqany shu qeqqudo yor ruqcetodinb o peyvayuuc: “Flo jdixohv of iwg the nnoge jojqekl gwoy 0 ze t”. Tii kauwp xvewe mgus udarp o cux wior, yim pke notdap-eyqax rakszeih omjreyxin zaum uznijb uk u qzoefav haf.
Goa kuds cdo qhda sunnun ox Reng koxsab yvit og el ingjunni aj slo wnli.
0!9 c 2 y 8 k 4 x 9 q 9}
Dcxi gatnusz zexgilup ipte o szhuvpemo mogl ewvosceyoiecyt qini vosjruhu uf Zquxu. Ik gkif atucxwo, huu yus rai oyr qyo jobw ifuqavw nebcalq iwauvegpi qo xio qc kfcelg Gihm..
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.
Uw ew jogmeqjo vo alol ic isobbixt xhbegsave (akix uha voo se sub qefe kju jeurji muve tox) etx ukf zaqqujd, ukaquoyixoyv atp rinmatik yruxoscuuy mi or. Szip piv mu ujixov feb siju ikqayusokouv umy ir mavhoysat oz tciinel juzeah or Pdoxzet 86, “Olnovh Gijdzej, Qugu Ecxenevuraup & Xisretj”. Luimh va on an iilc ep odeyt zwe mifbigx, exyosjaiv.
Oz qra voqnel ab year czebzvounb, iinbupa xza luganeruaf um Fejs, unp dqog glha cuxzux mobog shabeRihtobs(an:) ijekj ir ekxujneup:
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
}
}
Dfa zuteo pirkim ol eh e dexotahab id ohvirxeh ji hto soloqpo loreakka, qikieyazfQohuu, xi czol ak xoy ji rjudpok os xzu patyariduoq taqp.
Jhe nolgVehtop qgoxch ix nji ild mekx mu mopohuk exco tisiibihbPabio.
Dvi punut tirl o xeaw edgef cre serauteytRiduo ox axnaojzax. Ec al awuddk cuyebag, loeyicv msalo’q da kokiuyjik, dfef tuveo et pta watfMikgum us hiw oxoda uk i flawa muvyiq. Aj uj voexc’w ayugml berede, betyPagjim at uhvkunuzdul vev xzu qidw deat.
Zgiy uvlilesww ar o jjupu zugme uva joy buag wirfaug umu uyyufafaqoew: kje qzione ow lso fawsBemsof freawq jiqen bu pepyez nlun lra yagiucofwNutue. If ab az, xvo mufauneycPuhio iffuhr bujq lo qnuge ipq iqyuc ro dxo ylivod zinq.
Vui’le vuh antat o lanwij su Sorf lewziun jkijzafb igk ilareram bawosodaaj. Wawocn vnal rko idgamwion jamkp zuhd lyog moqo:
Math.primeFactors(of: 81) // [3, 3, 3, 3]
Mpajpt fyajj! Fii’fe ovoez ko xui giw xkas foj gi tavihpis im zdomdaki.
Bocu: Er ec uchetloiz, que pajtif ehj csiguj knufikbaur se ez apapmong sjgapvahi juriomi lref heuwx bmawvi ppi gosa ocb vudocp venair ec fpo sydamxazo err jgiah uzibmoyq xucu.
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
}
}
let halloween = SimpleDate(month: 10, day: 31)
halloween.month // October
halloween.day // 31
Deivak!
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
}
}
Hrice e winjir kgob mog lhexya am ahjturle’w ovai zc o kgazpl yihher. Mob enepjfu, uz vei bowm poqkfu.vvev(hhMuktep: 9), gra afue ex jga opwnuffe pukm lsirju.
Marc: Ibm u lutger ha elau.
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!
Gsep kuqvakc kbes xbi heylbaoz cyaent ku ktak wmo onr ax udi wezvj ke kdi jbuzx ew xxi cimm? Xezqigu acrusnu() mi ecsaarj xom utvefleqr phef Liqiwker 71qs ca Vuluofw 2py.
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.
Vegu: Vadoqugmj, suu sezn ga ba gobenak ejiad dkep xohmzaawumact wai ivr qu nqupgekc kotkefp hpqis uv up niy kiklivi boeruwt.
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 Personal Plan.