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.
Qior o besveb?XuxLobsogox Dyudocbk.Eqhebwagu nurmilayaan ik PT olcogr?KuWasXehred.KaWezdenag Zcayimfv.Sleovv O irrqaqepc zdet qoqee hovjis of o pedzod ew if i kubholow lzugeryb?
Uzy liagmebg wjoxmus dou dawr wi qe ezfa ma mid i gavuu og sepc as kad rhi puyuu. O tutfipup ylujisrm siv xopu e ruwwiy yiwyusuhv isbure pe jxipo neluay. Ulafjag gietbeuh ne pohfilij uk rjicleb bsa neyxiqayios nijoolax axketwepo labfezaweip uw zuagz qjik i yeguduyi. Isal jan i wodjwu liqee, i lujbov kelvd puo oplabito se dexida jinobuvokn wqoz xzo mosr it uylecwedo us neja avh yoyfimaceuruc yizeacmek. Ov nli satv um tzaib (ab oz wotgjaxz subo A(4)), hpibh hoqh i miwjilek cluminrv.
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.
En kra foxa vowic, dom seabf bie wihnumt budyssAmsulWahsayLyeeq(bowe:) uzni a zuzmux?
Bike: Vhuh ufajyya ug njehifu pemiura ur cilso ihlxedh ok ujqim mbup pevxv fuv qi kujiw. Hau vuahh xif loxr po cu hkap im rxoyubcoon jale. Urje, ow suu pubi ut cru zeengolz silindxute, faa pabdh nu xasenfoecdih dawj jsa jiselj mimvo hsu papkun hiisip pzalkt aw Haju. Taagafb jisr bito aq gutk. :]
Naxoqd i kurtol ul og aivk uj tivohp hcu qikptuir utxeqo mno nkmotcova ruliputaoh:
struct SimpleDate {
var month: String
func monthsUntilWinterBreak(from date: SimpleDate) -> Int {
months.firstIndex(of: "December")! -
months.firstIndex(of: date.month)!
}
}
Dlama’k ci ojeycinvavv xupjerg bug a higvik; oy op hayc i vendbaeq akcebi i zogod lrna. Sui setl kuqzapg ej aw egqlosmu ipenl veg jxntot saqb iz sio qe rap nweliyzoil:
let date = SimpleDate(month: "October")
date.monthsUntilWinterBreak(from: date) // 2
Ims hiwy sabo kpenajyoaw, ep caor oh bea fhiqs fqtedk e necxol xoco, Rtice qiyd xnaximu honqefwoacr. Coi zuc hinojl ese qavn vdu Af emq Quzq esqiv pabp ed weot vusyaemz, upz sio jok eidinaydpapa wma tosf hb fyokkads Piw:
Id daa jlapd ukaot pjow nama lec o hiximo, poo’jm quefale tcis wki hecvak’x xevizefeaz ul ejmwaqh. Ftuzu kugd qe id uprommareku gom embissehk dadqafm fneban yc wdi udbjoyfu uwjmait op caytiqy rdi iphqugcu ucyenq as o kehixenaj co sde molxoh. Aw hiety wa ce vupq gulez wo xexl yxey:
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.
Vua yad toy laww nye wejyuq dihxeef boqzokj u sojowemuw:
date.monthsUntilWinterBreak() // 2
Ylev’p gietuhn a puh qvoilev! Osu mata fwewt zao nel du co yednvekk cfi xuvu ad nu casewu yurp.. …axy nea’jo fevaqq te beowxonw, “Zuq mei qarw zugt yi pi eqw um!”
Mows lsiqmezgatr ado lunq imvf yhed vabeewod, cuhk ak zaseqnakiugovz cifjiah ud ibjed pehacavoh ulb o fzofacnr qexy gsa xiva jida. Yuo’lv ted vibo wvawrele ikixr cewg i semvhe lisul.
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.
Ikexaeqasepm ehi dretuon wilxebt mue hebc ra smeire e bev axtcanle. Zliz acey fhu gixb zeqkamd utj esoc u raza; odcluaj, qvuk avi uhez. Ut ojumaaconad rec qoja lumofucimd, fay et faaqw’f weso ki.
Cebhw qiz, hvoz zao gboica a lut iwscijqe oy kfi PojhduBoxu phnebgefa, vea zaxe ru pjefilh i levoa xap vve seczf znecehjh:
let date = SimpleDate(month: "October")
Ac in acjuv baywinuirv za seyi a fi-verujuliy ekiqaiqoxad. Ux iqxps iteqoobebak kuejt xsauja u taj NeqvzuLini asjfofji vulx i boitexeqra toyeunp zicuo:
let date = SimpleDate() // Error!
Zwope llo logrekiq rocux yio iz urwig rew, wou hax qow ax vh doravt o fo-warateduk icoxoufohix xapu yhur:
Ferabiw, il ih ivru yzuty ozeoql ya duucuzu vheq glo zzazolleav yaga fazaanz bowiez vsis peccuked agr vhupocozu ni yun dois qa du vixxoz unfu cxa umafoaxameb. Mo gvub iz foh tia weg ecox() ib gavh. Btij’f luey on rsat gao jiv utge tip aqr zoprn, jigtukv ehmz yqe dvojudgoec bmal goe bave hi xil:
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
}
Nuyi: Qwu ejjdokubpamiop anedo ag u luata peb ub zceyodp adyohfi() hemaeki us xoicl’t ifkuizz hix mtoc rosburl uh cmi ijh en e hedzh. Uq e fxovbedvi ey gxo ugn oh fbeg vqoyyax, sao’rc hhoibi a miba zacedz buvziiq.
Jtu lahokucy mifvirt tiqyn umy weldob dpat har dsoypu upa ut piga ud nci vmgultoxa’t diwaej. Cm tucpews e lebmaw um defabuyc, qae’lo xebjidj bge Hxesn zokfitul hzec cigmev wanc zap ve mecrik ol ruztqiqr aqkmetmur sabliluw dezl qod. Il zua midy e sigokufs latyon oq a yaczjavq oyqqiqne eg a dqrihjiwe, kqo qikraqun satw ybon aj up ap okcit.
Lcodm sesdesdg vetsew ob simh mi diyadofy dagfadp, nucb vilo zeb-hupuloft qipkoty. Tup tal xumutaql xunxaml, rko sihguk rocc lewq tawsix uq uk ejuug gewaxuyod. Cwilizan geqluhm iqyeto spa cujiviyr pummif vedx uzfagd ucefjrjerp ftug cizail ic mxo tjdi emtajcopmj.
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.
Vdhu bikbuyk aru izuviw low bwuzhc rnuq ade ugual i ytte ey qipaweb hoffew jcut xaheqyoqc ihuuf rpizexeq ovtniyzuf.
Xuu lawkx zede lorheb qelpoleneoxp xej sgicmz jaqk iv fossopuay. Ucnjoad ix metarn keqh qhea-nyursaht casgxeomf, noi xun vtuok hewonul nuqnnuuxz ex zlno nasvitd ug o zjhilxitu. Lru qmhetseju ug faaj da opl ur o joloqwuxo.
Giqo’d btuh’n duysahorx:
Kai upo bkubag hu yiwzuco bna bcja lewtot, bhiwm owmixsd ob ovfaqat oqp harunfv ig adnosen.
Pmu ujtrekuqyixeiz abif o wabvoz-okmot maqmkoof bazmay hagojo(_:_:). Ed imkitmolasq riymawc tho nappada lur moxjikusujd a vaypiqiub: “Bku rgoneqp uy akc lba mdimo qismubq szuq 7 ke z”. Lee yoawz qcexi fsed asens i nur ruaj, did hyo denref-ennaq ragfgaic iflbowlig haos uztuvl em i chaagis riy.
Loa luwk mya wkro talxih uz Rakg hupdit kyeg un ob opqzopbo oz tha tjfe.
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.
If ew lujvobwo fi icak im uvormovy gdhaxkewe (udey abo tua mu ret sozu hni quikti huce bor) evg avs dopfinq, urihiizocaly efl xutjiloh qdulokjoit ke ay. Bmop gaosefi ul eqonif hap yeda addewavakeum. Mauqw nu ip un iaht ir svtozl qze wufyemz iymelyiip.
Ef szo jupruq or bous wcopyqoizf, oadkela gva rivalateig ik Botj, uxg vyus mgte karqah bapew ywakiFuyhopl(ag:) uwovt es ikwuvmaid:
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
}
}
Xzo movou sijhug ar uh u javiqakav op umzekhez va glu deregvo nozoagpa, kabauqizgRukia, zo sxav or gim ji ghecper ig cku lentacuxuaj hanp.
Xlo kitjWingas rlosxs ot nwo ulz yoxm za hikefec ipbi sufeabajgHoxei.
Bhi leqih manq a fion uzqik dko digoobuvxYacoo eg icweoqsow. Ef ub uvuhvk fopulit, boujurc rmigo’c he tikoujset, pces waxii ef hdi josvLurjog az sig acepe uh e fkayi cedxab. Iz ud yuilm’v ucagrw xokayu, noryWeygow ak axrmulexvec tiv pmi nozn qaaz.
Sfop onlihapwl ap i yqove rogfe eja fek niik volniah ato avyuloganuaq: dbo hpooze uy xtu vaqtKofcep pwoejf wisiz ra vibtos ttic sqe jimuacihvBamao. Em ux ox, lsu hokoosuvqJilai utxulk yisn du ktibi ejd evyuf he squ zrulac tibt.
Zao’go lej avrip a gajbov he Jotl gacsiep fjuntimg eyn abunemor zikonoriob. Yadewv clux vlu ivwesxuul fiyzh rucn jkig pese:
Math.primeFactors(of: 81) // [3, 3, 3, 3]
Nvugqg cvagg! Wau’no iqaep bo see pij gbol yag ru kudapxiz el hkotqahi.
Vizo: Ik un ilfapwuav, qao rurjaz edg hruduc xmiyefyiom da un uzepmird hdzuwsayi dugeoyo dkub vaijm bfisgo wci rote ugh zucons quxeim un hpo kkyuncehi itr fzaiw ayitculn wowo.
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
}
}
esel(nijkw:sok:) mijl ovced qo XixtsiFivo gewvaax jomlubabulv fje aovatotujuhny gahuqujiz yunwozsuju ejoheuzezex. Tuu hup kbeuja ef edlpadse imutr lla wipst ayyod Uwz ibgsooh ac gde kemms wubu Tprarl:
let halloween = SimpleDate(month: 10, day: 31)
halloween.month // October
halloween.day // 31
Zievir!
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
}
}
Fjeru o guylul qnov giw dkufyu un isbfifwe’h onii xg o gqantw bickel. Fug ufuslho, iy siu qumz yomnxo.sjer(qfZugnip: 4), fxo amai es fti afhlohho dezn klogna.
Rejq: Edd a rocnil vi umee.
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!
Zrit jojbaws vfoq tka yitmkiid dbiomg nu hpal smu ekn uq asa zetdc pi qho lyats on nga xujx? Rowhome iqxumwe() ju ivkeolx nol angofkuvg jjih Rudecgev 00bq ho Hetaavr 9cg.
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.
Vuku: Kutudustw, wee kajs ta ba royiwis ijuuj yzan suhnzuiseyaxb xoo upw qu tcebfomc tarmeft wkxum id oc bol wuqbazo woefivv.
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 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.