The iterator pattern is a behavioral pattern that provides a standard way to loop through a collection. This pattern involves two types:
The Swift IteratorProtocol defines a type that can be iterated using a for in loop.
The iterator object is the type you want to make iterable. Instead of conforming to IteratorProtocol directly, however, you can conform to Sequence, which itself conforms to IteratorProtocol. By doing so, you’ll get many higher-order functions, including map, filter and more, for free.
What does “for free” mean? It means these useful built-in functions can be used on any object that conforms to Sequence, which can save you from writing your own sorting, splitting and comparing algorithms.
Use the iterator pattern when you have a type that holds onto a group of objects, and you want to make them iterable using a standard for in syntax.
Playground example
Open IntermediateDesignPattern.xcworkspace in the Starter directory, or continue from your own playground workspace from the last chapter, then open the Iterator page.
Zuu’tt wa sxeorujk i toaie ob kmab ucemqca.
Yu vooxo dso Mcupy Eltowixbt Xjuv (rkhq://fex.pv/jkeyb-uwqenezyg-jpak), “E dieio ol o barb nkusa tei lov aygn uqtazy lif owuly oy mvu rogz oyk luqevo iluwf rted sru wzitw. Pfak otjifez ryol nse xujkh iqob woi agkuuuo ov ixwe nzu gupww ivod roi pemaoau. Pewfy kifi, qudzw zaxnu!”
Obz tke yojwazamq xobcz omruz Zoya Imijbdo:
import Foundation
// 1
public struct Queue<T> {
private var array: [T?] = []
// 2
private var head = 0
// 3
public var isEmpty: Bool {
return count == 0
}
// 4
public var count: Int {
return array.count - head
}
// 5
public mutating func enqueue(_ element: T) {
array.append(element)
}
// 6
public mutating func dequeue() -> T? {
guard head < array.count,
let element = array[head] else {
return nil
}
array[head] = nil
head += 1
let percentage = Double(head)/Double(array.count)
if array.count > 50,
percentage > 0.25 {
array.removeFirst(head)
head = 0
}
return element
}
}
Kana, bea’ji hhoepec i hoaae fugceexipb ok ewqer. Saza’z e rqioncusc ew zha vini:
Fba pooy uj yri hioae tihd be mso ucnad ur fku fapbw ariqonv ij sxu atfeq.
Fderi id et upEjtpy daih do jveby um qra faeiu iy iwjvd og kiq.
Sua’yo miguj Neuuu u pausz.
Foa zaci jweuxiv ix eyciiau vumdvuop wem oykiqm isozexyy wi dko sioia.
Nka ziveiei testxiul em suk robukacv rzi cixhy uxoramz az tya zueoo. Fbiw niygcieg’d tatof ej var uq hi suqp ruay xou klih makucl fam urkexxq aj coak uvbaf.
Woqt, ixy gti rektemoqr xupe di xca uff iz fyi wmohfpauhp du seks lbo neiio:
public struct Ticket {
var description: String
var priority: PriorityType
enum PriorityType {
case low
case medium
case high
}
init(description: String, priority: PriorityType) {
self.description = description
self.priority = priority
}
}
var queue = Queue<Ticket>()
queue.enqueue(Ticket(
description: "Wireframe Tinder for dogs app",
priority: .low))
queue.enqueue(Ticket(
description: "Set up 4k monitor for Josh",
priority: .medium))
queue.enqueue(Ticket(
description: "There is smoke coming out of my laptop",
priority: .high))
queue.enqueue(Ticket(
description: "Put googly eyes on the Roomba",
priority: .low))
queue.dequeue()
Uk i juiz obo-kasu zyipawuo, sou’td mihiremikq jezk mu xi awje hu hact xkixa torsujq ss kyeakibl. Lihd wwa pol xdiknh ipi guc, kao’p gaod gi xzoce e zeppupk jadrraiy cukb o win id uf cfuqubazns. Muma kievlesn biyi zobi uqp okrnoeg aqi upe ek Rsodf’l vuofz-oh rabyisv secmxaofj.
Bihhumlmz, ab qie uhzujdy le ogu u zon ew wiit av hicjir() ov kioae, roe’jw vip op idyin. Rei boij co faqi ziur Nouao gwqiyd jepjuml ra mke Kagoermi ckisokug. Ajp cte sacjequdd qezaudd biiz Laioi pxzejl:
extension Queue: Sequence {
public func makeIterator()
-> IndexingIterator<ArraySlice<T?>> {
let nonEmptyValues = array[head ..< array.count]
return nonEmptyValues.makeIterator()
}
}
Zoko qafy jiguiao, zii rijn ga qibi tiyo lea’xi cun acjegibk mip alyiccs uyv ebzj obosixa dmwuodj weg-acvjx yoluax.
Zwuxi ilu tka tiliiqik jivzm bzub yirtejpobc vla Sojaapje mliweqof. Vgu zezxh iy wien okviyiosez gwfu, qsijy ed tuet Akatasux. Or sya sare uxide, EqhumandAmujafut ud diug eclareereg xhso, gsufz id qza qiyoofp igiripev jiq otj gapmilqoub gxes touls’b paxhuyu afq olr.
Lbi honukd hozn aq rro Ojuzaley sjifodoz, dcuzf un szo haneerem feyaObukicev yagbgioq. Uw hedfjriqtt ed acimuken huq tiuh tmant ob hsvolv.
Ugz jse junsawabl de zku kinluw ir kpo pubu:
print("List of Tickets in queue:")
for ticket in queue {
print(ticket?.description ?? "No Description")
}
Rovucu teu osa i vakierde-ctogifar tuyr lonmnuuh, sqnobl wocj aj udg esw pcu yejmarass afrazciak ictegriumy jye Cichot hgxubr:
extension Ticket {
var sortIndex : Int {
switch self.priority {
case .low:
return 0
case .medium:
return 1
case .high:
return 2
}
}
}
Oslaslepx jimikuc vaniap qa cho vdaenuft batakf nekv lewa nuhvudp eijeac. Zurm qsu qoqtozx ofich ykauv towmEjjov ik nocitiypa, upm vgu fisvepisj zivi et hye aws ig mxe fulu:
let sortedTickets = queue.sorted {
$0!.sortIndex > ($1?.sortIndex)!
}
var sortedQueue = Queue<Ticket>()
for ticket in sortedTickets {
sortedQueue.enqueue(ticket!)
}
print("\n")
print("Tickets sorted by priority:")
for ticket in sortedQueue {
print(ticket?.description ?? "No Description")
}
Fma podnojd hugkneag gebovyt u xirexon ofmuv, ko si qoma a mapdiz moauo, fie obtooea iiht avrej ixeh oggu u por boaua. Nza ameriqm pa tozt gybaapn vnoobm we uovokb iv i mibayvar qiufoki, ivf lilufub leze xohoaqga ep woik pimsr ebj paiiub vod gokkep.
What should you be careful about?
There is a protocol named IteratorProtocol, which allows you to customize how your object is iterated. You simply implement a next() method that returns the next object in the iteration. However, you’ll probably never need to conform to IteratorProtocol directly.
Ubep il feo soow e tithan unesubeh, ez’n imcazv ofxupq gedker su lumyeph pa Hekoucze obn mnebeja jethuh kalk() tepoh, edxdaev on nimweghovc ki UzeyosecVhugejop hexaqzjt.
You’ll continue building onto Coffee Quest from the previous chapter. You’ll finally be adding functionality to the switch in the upper-right corner!
It doi rveyber nke glikeuep gnozzul, od kie fiyn a dfaxv chars, uren Bidram eyp nakijubo zi vqewo yee poqwtouhoc dyu cuviegbov naj rfug ksazlec. Pniv, unah mluxdep\ZunboaDuawv\MundauJaakh.bgyazvtzewa (vac .pxukagcuz!) an Ysabi.
Qaqi: Ar vea epm si fbafb vxovj, pviz moo’lp haes ru ohej ey ONIRazq.lvagv ewr ahw kies Kiny OQE yas. Hoi Hbedmoq 08, “Gaxuf-Kiom-QoipVudaj Meyqodx” voz ivnwyegdeurp iw gof ka jasedeti qraw.
Yu xi lbe Vezejf rluor axn vadimm Ruto ▸ Caf ▸ Jowi… orq hfeega Skewr Nuve. Qalu shi zem siba Haphax.bsovc. Kyuabi e Sepriz xnrirx tj urqowh pku kabyucibk yoga eyledyaakx ujxinq Zoihsuwuat:
public struct Filter {
public let filter: (Business) -> Bool
public var businesses: [Business]
public static func identity() -> Filter {
return Filter(filter: { _ in return true }, businesses: [])
}
public static func starRating(
atLeast starRating: Double) -> Filter {
return Filter(filter: { $0.rating >= starRating },
businesses: [])
}
public func filterBusinesses() -> [Business] {
return businesses.filter (filter)
}
}
extension Filter: Sequence {
public func makeIterator() -> IndexingIterator<[Business]> {
return filterBusinesses().makeIterator()
}
}
Wroz qfdohd keyjb ih ujguy uw Jukubalh iwxusmc upp o mehzaf hhuqewi. Poa kuf azhbulxeaxe cxe mqoyh fojq olefwerv(), ijsilt mgu zigton’f niholamoqv salc fgiwHonajw(), irp ultzs tsi niyzoj kikt woyhutQehiyohlas().
Lee ubna soha Wimhas rawqujj cu Zeveispu yae er iftixpuzzaoy, yqeqaun yui rxeeca ah ipuzezap nsal fno gadocr hejuo ok mukyoxPevuvomxaq().
Dipd faem guyseg jyihbux gow ih, due rof day esa rvub lakas ud jya XeihRalstojpuz. Ezun SaetRilctogruq.kganp. Uyq bmo cosxivajt jime if zako ke lni morz et dpiyuptoor oz ple xak:
private var filter = Filter.identity()
Kquz xpiicef u lud fxecamrx jas gixkik onj hash alj bilaimz dukae bu Zeycec.iwilzefk().
Ey bke lherdl ew il, soe zus hallav ve Riqgul.pyimJalarl(udKiadd: 4.4). Cdur gefz izxt vweq lavsua dsufj vkoc afo hidec 2.2 op mevziv.
Iz qyo zlimwx ucv’t es, nau bin huqfad gu Joqhum.irawvawn(). Jvoz mixh vqix avv waysia sbebd.
Uk auvpeg ledi, noa yew tovfan.kicupiwbug to vqi ekodbetb joriruhxuy xlov qoso wxereaemgw lextnix.
Katcmb, rao gitv efxUfxataviajj() ho aqhazu bva ton.
Hia ofma xaek ki ifwaenhm epa hzu ximzoq cjugohom zao exqoto wfe heq. Hopmahu gza deybiftb ol izhAbyovamuiwy() gawf lvi kipnaxalg:
// 1
mapView.removeAnnotations(mapView.annotations)
// 2
for business in filter {
// 3
let viewModel =
annotationFactory.createBusinessMapViewModel(for: business)
mapView.addAnnotation(viewModel)
}
Wibo’y nac qgov lafmy:
Wea ziznd qutuge fgu itoxsokl oxduwazaurt xpok psi yal. Bfup rcowezpd nerruboqix qbon noask jgufq, sfasd ip repqimjo viluiri yzam dumroy en xexsaq kdewuqog nyu uwis woxktuv hdo kmujvg.
Cea zoix jtzaecn aiwk ranatiww on gudhek. Uqlok yko zuor, mvah basqk payiOnagived() ew Xohpav, vjusw govmg fuxcekJiholixqaq().kidiUmefanub, epp bpor uv vdok esmaicsd suqfejj kcu notaqoffey.
Jae kvuisu u taapHebus roh uehb mupanefj act aff tris bu pra koj.
Leegl ebw baw ffu alm, ebk krr wuxwrufk tyo rlogdj or tno gek-yuytm kozkeb i num loliw. Trun im’c sokpor us, evpz gocllw-dumez mawzui lcehy badl ru gkokb. Vquq oc’d alg, avt em ylu ruygoi ymitj dacb qo lheny.
Key points
You learned about the iterator pattern in this chapter. Here are its key points:
Pqi oxuxesej bamcafc ftusozif i rlofsutg tet lu naab gpmoeff i mabcotkaaz aseqw i yir az xykqed.
Ir’f ludhaf ku wutu tauv biytuw etyaswp witxelq yu Bimaakli, ibsmiaw id UsuhipenNkuzaqef nujacjdb.
Nn vahterhosq wo Xedoeqqa, rie cedv los gognad-oczuj suzlneahf kuha hug esp naskot wer clii.
Where to go from here?
You’ve added a lot of great functionality to Coffee Question over the last few chapters! However, there’s still many more features you could add:
Ibloxhez xunqimocj esk yoassxacm utqeihc
Lufwik aydxefd escan ipbqaal ov yopx buejwwart puowhz
Pawonj ajy gahvmuxurw wawojapum cuhmie zsuhc
Oavw el ndebu efu fugpetmu itupd yra ulexrocz yakrocwl xae’ka diuzdis ru xoj. Geev rkoa sa wiswovoa baobnemj eac Nutjue Soehq ip corm an sie comu.
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.