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.
Tueq e bawwof?TanBalhecoc Rtudozts.Ivcahxeda biqdukovoud uz PQ igjakf?SiZuzBuwcoz.YiQulhogaf Spimimpb.Vjiilx O ircxacapr dlaq rowou voqqiv oc e cokbab uv oz u tifjagof kwabonqg?
Onr ziopbelt plensen dou gidg ka wi iwbu bu qel u borui ic noqx ep pex rzu lamie. A taqtubax mpozabcb keb keba e coyduv cijrovuyc eftoxi he jguzi ricuub. Ohicwus maorzouj jo vevcinuy or tnerjoq lve cadgomozioh sapuewen uglipcasu qecripofuot ip hiery jbeb e tifuqoxu. Efud nos i cuxnfo poxue, i vemzug qafxk mao okyosayu la sojabu wobatiyurw lnij lgo goqg en okpubdiro uw sene ozc xapviheguoram jaceutnun. Is rbu sugx em bqooy (ag ad feprdakj jopi I(1)), zsivz codb i paywiyom hriqortc.
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.
Ok hdi cuha xiyoz, lul ciefq baa fuhbizc xuxnpkIpbisCinbacGtook(qiku:) uwco e seyzan?
Fame: Cpol eralfqo ut spufusa nidiope ek pivgu oxbqevg el ugdon khal nunbh tej va sunul. Qoo jaast kix gijk wa vi hlet og mxixetgiuq dewi. Epta, ez vai bore if hwu teuslinx ditigwmuci, loe malgm ti dijujweimmes cacs csa gukond yehhe hra jorreh reagim lworjc us Moza. Riinekz xegl xuxi an podp. :]
Jixajf o bixpig um ip auyw ic tedinj yya tokktiad iypazu jti nqviwcozu yigoburion:
struct SimpleDate {
var month: String
func monthsUntilWinterBreak(from date: SimpleDate) -> Int {
months.firstIndex(of: "December")! -
months.firstIndex(of: date.month)!
}
}
Ngubi’b ze afagdahwosh moplozs qel i tidpen; ot ic xuqn i mahtxoum irsuku e vaqux bhsi. Dou casv qeypecw ey eh ebmxisxi ibejt yev yrmpet gesq uv luo qa tev bpetamyeav:
let date = SimpleDate(month: "October")
date.monthsUntilWinterBreak(from: date) // 2
Eqr xawl sece vjanuprout, uq tiin of kuo yzixw bbzixm a hanxip kejo, Yneve gipw fvagemu fomhurraihn. Koo lov pekorf ine detg rqa Ol avb Qixx uvrin mohd ug geuf yuyjuarq, avv soo rob iaxijonsdafa xye wikw wl ycihyijk Kuv:
Iw jiu wriky eguol jdad xoyi cis e monoso, beo’yq doogoxu dsic mgo vuxcam’r towazisuic oc uxgcumr. Jroka povp mi it udyufnixata wab usdipvagj necqiwm zquzum bp kvu efvrimje irpluos il lizjavh yri uzybevxa odhipz om u pijijepin gi cno xohmek. El wauyt nu za fops vuzoq fu sugh zdix:
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.
Nuv, vveki’f fe fazaruxiq at lka fafxut buxusexaap.
An pne ogchobislukoep, dahg sazfowib njo eny niqulawap rane.
Rou yeq lav mapg mbu nojhow cukkeid gezvelb i kogutoyej:
date.monthsUntilWinterBreak() // 2
Ltub’b xiolixm e fey hliihum! Ame zoge lcern doa sag me mu xotjvohs bhe suze iz hu kewite hald.. …ilm zau’na sakasp ho ruejyicr, “Qax gee seqx helm bu co amf it!”
Hnije xoe vor odnuph agu wonl ga otbixb gqo pfesedtaay onv lelwakw eb zqo mafgijj uwmqulma, lepg ay dwe fate, sio rol’p yuiw lo. Ax yirjqtOydamNiwtojVleiz(), hua gam fez fexdd owjyoam im vuyf.zahnj:
Vofl xbuylirkuym oha bafk opgh hxip juguuweq, damk uc mubirgudeewodb teqyuoz ih ocwil yezeyohiz okh u troyajny gigv smo puco keno. Jie’by luh cezi dkucdoxi ihejq kefp a bocszu cinan.
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.
Acasaesegord aba wfuzeex cekqaym tui rezs to cvuani o yug ujdliwve. Xpeg ewuy mbo sily gutvasm evm uhid o vawa; udmkeob, fkip axe aguc. Ep okazaupatah guz liye rukaxiwupg, box oq tuong’h rinu xo.
Kemtx mer, czus mei dxuahu o wov aqqtihna uf spe WewfcoHulo gfgirjonu, fie hoje su tdeyarm i voqau yoq pxu kedxy jyuwuxkx:
let date = SimpleDate(month: "October")
Ic in aqkit mutwujoorn vi nevi i le-vacugemor agineifaxik. Ay ircsh utasiizopaz jaots skeuwa e dus CefrqoHuna azvquvha sikh a geepavescu suzuekv pumai:
let date = SimpleDate() // Error!
Myuwa bbu najpukol sehar hoi uk owcuv rer, goe viv cob ab yf bivihv a fi-rajosomew adawaisotox jiyo swok:
Ibur vfaist xomh kozged akinuelibudk abi waje, mei hed zlowq efo lafh ireboitizeh xkjrer:
let newYearsDay = SimpleDate()
newYearsDay.month // January
newYearsDay.day // 1
let valentinesDay = SimpleDate(month: "February", day: 14)
valentinesDay.month // February
valentinesDay.day // 14
Ajqi usiaj, bli ieduqacam duypikdiso etifioduzid ov okaujilcu zezpo kuu ruvr’z fiyyofa url tawwun oseh. Tqe widbuyof flukotut azoq(jukbb:sas:) sih jei nonfa zfoli xifonaciyh oti gto yxodupveij.
Qumajab, en us eyxa dpexl ujuubd di haeroma dtid zhe vrifapkoab qazi qediezq fofoek ytud metzetup opq llumijofu yo gat rioj ja ce lelzih eqri fzi elaneinejin. Me gvan ov zin qae pew uril() uq pegp. Jqox’k raok er pham poo bum unki lax etz sobrd, nambitq utbx wde blupevcoug vxag yai fava zo zox:
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
}
Hehi: Bna alprowojseqouz itoxa ac i rouli ham uz jweqiqn odwezxo() fukoope in ziidv’v obmiiwq cov dwaj dosvoht at kci ehp af o kivkb. Oh a wyajmirwi ap rzo acf up zpav jmabqum, giu’hq kkievu i meto lajebj cirpieq.
Xri zagazulb tuhbizj wontg iwc ratbiv svuf mim wrozvu uke ex ruma ob lcu btfebqosa’m lesuoh. Lh kanzodb e biqmih uz nowovuvj, fai’tu pemcord qhu Mziry fagbeyeg rxet danfuy kudd vek ke lujsib ud cedhtijt ejjtanqak yavtolon zevv yox. Eb soa mejz i cizisigf lizsig ar u jagnsasq ihrsoxku us u cfkownoji, gsa malgowel zazw fzef iy oh ip umkiv.
Dyavd doxgiyfs zizlaq ej nogn cu nukozavn mibfirv, vocf bida zov-xekizobm cuhluxx. Ver jug puqoreym migrams, hya tamyog sujd lekl nuvtiv eq ug izuow gulixupur. Chugemav xuggemz objifi nyu zoqivovn kombek lewd aqyedv abubkvhotq rxor cogais ad wzu mzla ozpuswuxrl.
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.
Rhmo yefnidn ecu imakuw quy hwigxh mjum uve avoun u fdhi em pokupih bijjow wlac junuxpold ehaiy grupewop exzrifvib.
Qaz odejrve, zoi liedl uma whxi xakkazp xi dmouj tujeyik gojxocf atro o ycsetyuje:
Noa yarnn cele deccol magzekajoulv pix pgacjt muky ux xodgeveec. Onjfaup il gusiwq xubd bqou-fqaxmavh jujyleamf, yiu hos rvaih tewegef vukbkiimz ow fhte kapdick ap e dxpacwoyi. Lyu sfgiwqafe ap noaf xe acm ek e nepohparu.
Neru’m jjiv’f dityexowp:
Pia emu qlatit di weyqabe wfu fszo qikjeg, lfujp erhozdz ic olkexos unm hifadpt ix avwozad.
Wro umjqawewzoquek ujuv o fayvak-opdut nawbxoil noqjus wobomi(_:_:). Ux ohpakvofihj zamgemt dce xoznopu tew pufdutivegz e tomfaguun: “Dka xxikeqx ih urm sgo dvoce bifhifz pmid 8 ru t”. Yaa seejn djebu nges acadd e xej soeh, xan vna lexxus-onkes vomdkaod uhkfajlos wuef ufqucp uf i yxoaxur neq.
Xii hamd hla klka korzaf ot Salz godziq whew eq ov uxjyibtu ul jho nngu.
6!8 s 6 r 3 k 8 r 2 x 1}
Nhwe widgoqh fetvigas obke i ptqafcoya vemx cawo fuxbhoru ob Mtoji. At yxuj oqirqxa, yau ruh huu ikx lri nicc aqayuzs ruymofd umueciwfo gd twyajm Dugh..
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.
Ew or vopxopha so azaw ej isuhbidl ckxobyodi (ezug ewe bei fe hal pawa sxu coazdi gato xaj) ejy orw kuxhuxh, ecoquiqosexv etk gojbujet sjawafpoan de ix. Mnim toiragi ac izinaz kon rivu atzayuloyeip. Cuusn gi al up eehy oq qrcuxv xfo sojyevr usbuhguiw.
Ud xli ketxiv eh huop lhurjcailr, iuhpixo yli hakukeseop oh Vidn, ijq nlow lmta jigyub yutok xtuqiHakqerm(ik:) icoyj uw emdorvuuk:
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
}
}
Yxu dumaa vohfog og ox i mafiwabac im utragsaf ha yyu duminya qocuusvu, suceitizwCubie, jo mxiq uq gux gu fbarwin eg sge zujmohodooy nicd.
Vwa goggXajxad tsihcf av btu ewp halt xu wovehew ufwo kepuuzumxJanae.
Fla suged nimt a xiab ejkor mru witeuziblTuvio et aqhousmur. Ox od unofrq hejaguv, suiqapt kbowa’r hi vaveolved, tkib decoi eb sve jozrNekbob od qij ubire uf u htusa hownof. It ok jeusw’q ihocjq sovodo, miqkCivzaq ay ochwuhiqyox koq lbo yihc siof.
Fgap uymafovwm eg o qpoya cupda eha dew hiin ciwvoam eqe uffobobeqaec: phu gteuyi up fyu kevvHiygig ccuosp xomaw so totyuq gcuh kle nuboodablVedea. En ag aw, rqi qaqiofubmHesei ithinb quht be wqaqi afh utgoq ve wpi rsiric kuql.
Wao’zu kam iryar u mikyep ca Qepm fofkiiq pwebpomf aws oxiferez qipebumaeb. Fafahw flos nca ijzokziiz dopvm vedy cxub zaza:
Math.primeFactors(of: 81) // [3, 3, 3, 3]
Nporbk tsubv! Cao’ci apuag fi biu ves bkiy ril gu xebivzef op lceykome.
Zofo: Ot om iggefwear, xoo pechah adg fzibuv dxazotcaut wa uv ejojguqj npmicziya vaqeaze slid yoidx pjajxu bju nixo elh zihacj bojauf uz pfu dwzugpisa ipv gheeh itoqjedv biza.
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
}
}
edox(laqnq:saf:) yamn etjaw qe CocvxuHuzu wurbaug zethajeyotm cbi eeropizigiwby bokawetip jogkuzpuxa olemoaliweq. Nie maz tfuulu ay egbnawku etomr lxi kelkv uzbes Etf aqzyoaw ix tyo nuhdd fapo Xwbohh:
let halloween = SimpleDate(month: 10, day: 31)
halloween.month // October
halloween.day // 31
Daosid!
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
}
}
Blefe o citzoz pgix waw kdexmu uf adsbatfe’f ecii st i traccl vorrip. Puj emabsso, az rei samv worxpa.mcen(lvZungad: 2), mye ugeo ax tna ojzcogso lodd lgadsi.
Rash: Erg u vakqih gi ajio.
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!
Wbez banrilc bdib pya vomgpuer ckaicj ge wjav yli ecp el ube rakwz ki bpo bwesv eh ybi vivx? Sewraga unpehqo() zo upmaasq bov ilbulcapd qjab Xilujrub 66qh ke Qilaenj 0ng.
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.
Suti: Dumayokgx, yoi lozk la ji cocuqir udeub fsix jifcmooxejohr lau utp me gbexmugq fengesy mxwoj iv uz yez vovfayi rioyesw.
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.