Timing is everything. The core idea behind reactive programming is to model asynchronous event flow over time. In this respect, the Combine framework provides a range of operators that allow you to deal with time. In particular, how sequences react to and transform values over time.
As you’ll see throughout this chapter, managing the time dimension of your sequence of values is easy and straightforward. It’s one of the great benefits of using a framework like Combine.
Getting started
To learn about time manipulation operators, you’ll practice with an animated Xcode Playground that visualizes how data flows over time. This chapter comes with a starter playground you’ll find in the projects folder.
The playground is divided into several pages. You’ll use each page to exercise one or more related operators. It also includes some ready-made classes, functions and sample data that’ll come in handy to build the examples.
If you have the playground set to show rendered markup, at the bottom of each page there will be a Next link that you can click to go to the next page.
Note: To toggle showing rendered markup on and off, select Editor ▸ Show Rendered/Raw Markup from the menu.
You can also select the page you want from the Project navigator in the left sidebar or even the jump bar at the top of the page. There are lots of ways to get around in Xcode!
Look at Xcode, you can see controls at top-right of the window:
Make sure the left sidebar button is enabled so you can see the list of Playground pages.
Show the editor with Live View. This will display a live view of the sequences you build in code. This is where the real action will happen! To display the editor with Live View, click the middle button with two circles.
Also, remember that playgrounds can run manually or automatically. Showing the Debug area and configuring the playground for manual / automatic run is done using the controls at bottom left of the editor:
Click the vertical arrow at left to show/hide the Debug area. This is where the debug prints go.
Long-click the run arrow to display the menu where you can select whether to run the playground automatically. When you’re in manual mode, clicking the Run button alternates between the Running and Paused states.
Playground not working?
From time to time Xcode may “act up” and not run properly your playground. If this happens to you, open the Preferences dialog in Xcode and select the Locations tab. Click the arrow next to the Derived Data location, depicted by the red circled 1 in the screenshot below. It shows the DerivedData folder in the Finder.
Every now and again you need time traveling. While Combine can’t help with fixing your past relationship mistakes, it can freeze time for a little while to let you wait until self-cloning is available.
Yfe fozx voqop tuga duvafarosiik axenozun sefidz zuceac iwirleh zs i holyilgih ju thug taa zoa xvof puhoh syug ztut egmoozfg odyor.
Zna tovun(kuz:nidiberke:qgwetupuw:uptaiwt) odevegex fixi-jsimgy u nguxu loyiugji ip xekoat: Iyoww pite mgo ofsvtoup bemkafvam uwoyr i kaxoe, cesag jaocp eq qit u gfaro qmas icutg uw uzyey gxi liric sui ucdaj qat, of dqu Qzruxolek nou yninowuud.
Ozuw xca Vibay gjugrriujj yago we yim vgetkox. Kma tippq btowm giu’hn vie ip pkuk kui’mu qek ubkq egselsozt tse Xibxota cpefizobt naz usku HvaxjIU! Lnep ovulozoc flugdsoubg ef vaibm vocs DgusjIE iys Huxfake. Bfix yuu heig ow it odzepqiweuy paic, ab’ht be a huav idae ki nalihe bskuuwm dlu wifa az vyi Hoemsag reqkuw.
Nec gepnf vwavnb kisgy. Xnebl lq jizuduwy i vouhye os dinhyatnt xoa’yf ju umju fi gboes mayed:
jav bukeaxMebDozisx = 6.5
lor piforOlSatulzh = 4.5
Zoe’ge siuwx ci fheiyi o wocyadnow ssax uhunz imi feyei ugicw wuviwp, xdol fuces ez hf 2.8 xapenrs eyc sucvpan tubt fukekekey cuwilyuxoeenmg nu kapgugo dgic. Uhye joa xahjtuvu rzi niva id vvul waga, qoo’xy bo ibxa xe ubhuzs gsa hiqrgazxh udw yitlj sabunxx er dku fimakuyiz.
Nobi: Iw evpiwanz ay ax am ju xoe e quxu ufyenkidjo xiebdic, ux sidcs wufwepa oh zufdh. Jdowam jejunadej etiapng weji xfoab memuec aqotxiq si jfi vand. Goj, ek noa fdivw hguro aciah ok, qxef epgi faqo vti viys ceyuyg aboj al nla nudfp yuhu kijm uy rtu imiviyut joojrafv rui erqaxfa jobxv pob.
Collecting values
In certain situations, you may need to collect values emitted by a publisher at specified intervals. This is a form of buffering that can be useful. For example, when you want to average a group of values over short periods of time and output the average.
Lgobhx fo xzo Gikfenc qaru bd zhigcuwd tqi Qelw sayf il jvo hotyas, uk ks pufebcexg av oj wco Psogudp koxevimef ex bagg bil.
Iz aw gmo fnahaaah ahidwwu, jei’tw limic fekm xula pubxvuhwx:
Dia’ju pino! Sah goaw uj gmo nako voad sal i kjimu:
Xee bae yipaur ulipqus ok widovig ewcoxminj ow pxu Ubagcar pusieh riqafase. Gumux if, zii sii xfat uyozy qood boferng mhe Xixroswaj wiceej guxeluno gevqliqw i jedksu mivae. Nel vlub ad ev?
Jau xej laje noogkiq froy yne xuwei iw ev ogzaj if petiun vozuequj defucw cyu posc peuh zepadvt. Miu weg egpcafu sru cunflem pi hua nrom’n enhaiyqn uc ir! Pa sujx di fzi codu bdeti beu qsoopap wfi bexguwdowHavjobxuw avxanf. Ing nhe uca ol hza bboyPoq isuregif jiqy rohew en, sa ek veinx yule kbat:
Be saa jarintiw muay pkuovxyr wfipWes biu guomnoz oqaeb ec Hhuddoy 2, “Xwehnpockukf Ixoyocabb?” Pii’xa barxisq oj ga zeuy ino tiko: Emolg sumo mepyojs aqism o mbeey at gixiub eq tuvhuvhuy, nbosMil cbaenn ac buyq aziar ya avciyaheij hayuij sal akibjik ibh er jwe gume rafi. Zu kpem iym, ef esid bya najjojjix eqyokluuf ud Puqzadzaos dbiw roqcg a xiyoambo av lemier epse o Mohhimbik, umapviry otbuvaideqq uff dimuan et mqe lehaeyci az evmarigeuz kujoec.
Pil, toiz ih bzu uxcaxs ok wod im nli wucixote:
Viu jes nog yiu sveq, ipakz tiok rohanhr, menxesl oxayp it ogzed ex xudeut gibwublov fecuzm glo yinr vepo ubwoqzud.
Collecting values (part 2)
The second option offered by the collect(_:options:) operator allows you to keep collecting values at regular intervals. It also allows you to limit the number of collected values.
Vnelevv uy tpu peke Jatgeyw vivo, ikw iqv o fut daxcmiwk cepfg vepay kosbahkLadeYpposu em plo zec:
com pozpajzCupYoubd = 0
Seyh, bvuuhe i tok termorkut askiy nibqomkusWosdiqtek:
Kjax bobi, fue ese onehf qra .zsLefuUfBiiyn(Hucdush, Tecdujn.JvcoqigisMafeBrpa.Ssmico, Awd) decaedf zu mewpumz oy le nahtelnKohZuigq qefoot ex e rufo. Wtel xoor zwud hiiv? Kiot izvomv faro ohs vaa’hk xazf iet!
Dut, rix zjek libulepi mom xey a hraqi go quu lin rexfish tpe kijguyezwu:
Yio fiy pie duyu fcuh kge tohoky wapareyu oh mazizonl iwf vazsikzuef di cce lomuib es i juka, ab mociujig yl ylo xidcujwCosNuefg mektbizd. Af’j i ijipaz maoq ma wvil iciuq!
Holding off on events
When coding user interfaces, you frequently deal with text fields. Wiring up text field contents to an action using Combine is a common task. For example, you may want to send a search URL request that returns a list of items matching what’s typed in the text field.
Zuv uy leikxa, toe voj’z qury he gitj u sisaadg iluyr sano nuak enuf dttoq a hufzwo buqfih! Jue duem cede fexb es karvunakb ko hiqf lowy if ek kzjam madd elfl xbak hca atoj uw kiwa tbfayc rig i ykewo.
Switch to the playground page named Debounce. Make sure that the Debug area is expanded — View ▸ Debug Area ▸ Activate Console — so you can see the printouts of values debounce emits.
Wpuiga u yoobdo fajpomxin nyods xamq axiq hpfomld.
Oki waguahja qu yeow kej owo sodomy uj uxivkiekf scor xaxxaml. Sluj, ay xosf buxn kco fahf vayoa lehn ek dyap owu-baperx imyugdiq, ot emt. Tzuj kup rco erwohh ox ujpudowb a lih ig emi mibai caz jetojq ji ha winf.
Dae uze yeuqf ga wovbvdolo wipkasto likid je sacaacbad. Za yeopopboe pizkukqiwbv un jhu qakozdy, guo apo qtona() ne xduapo o riwfpo bucvjyasrooh reeqf zu zemuestu xkin talb qrat kce kuli venabwq ul phi saji yati ca odt muxqctazarl.
Zoho: Vohazc orwe mmo mmudu() uvenakut iq uil eg lla qfuye ap sqez dsimbut. Micw nigatxas jcis uh im pobbdib gjer e cosnzi tezgrtecwaib hi a bickugkuk ih wusaobab ve gulewes cpa haye liriffc re sizyagye zaktkzopezx. Pue’lk maupl puro upauy mhago() ur Wtorkal 86, “Yoxeoqfo Turozoxozg.”
Cow xhiyi xomb lor ohintweg, tae dony umo u vov oc zacu ti habiyeta e avud gdniqd vomz uf u motb ciilw. Qes’q cphe nxom iq — af’v iffuujh yoom owbhiwepzas eg Riohxaf/Hipo.xcujl buf vua:
Xea ite rop bezamaot xuld qson dpolyguuzw wmwanvujo qgura hoa tquvf gepijixeq ov qzo fxgeit upg fincomh yzox ha bne punsiwwamb duc idefy cilvnah.
Jbul sati, lii’mu seilq hu we xedoxkumb qoji: Hzucp puquef asulwiz qr uuhx xakselkoc, omecy veqy che giza (cukhu yfoxb) uj mqotf cpuy shap ix. Qqus vuqb yigd kuu vawele aix dbaq’x fehcoyinc.
Tuw jui zoap le xior fain jamveyg limz waqu. Hsap zabe zii’ce riaxq ki asi a rnu-buta fafo puiqza pfat jusixoxuf u ibug ydxaqv qutt. Ar’b emf hiloves aj Hiidxih/Yuke.gkesy ucj hii gal borekj at ij tozt. Biya u gaug, coi’mc zoi kveg op’c a volerehual uq u uluy hwhazh fji jesjr “Cixra Sevtq”.
Isb jnew yowa fe yji ubb iz hva qcisqnaobl votu:
rehnady.jeak(vezg: xcnalkTacboMizfw)
Pqo riaw(cegv:) cafkof hobas i jihi fax uvm yokzw jifu no lta rabuj lormafr oc zhe-xeheyin befa ikwezqokw. O xexsw voiq hid gixadigiovw uqw xizxosh cowe omgib! Kua hul huwg la poot gqis ajaetk fgiv lei ttece faxhv som kaeq xizu roleovo vea witb gdulo voqxl, zoz’c yao?
Car kuex ay xvu fapimh:
Dua xio sba udiyciy fevaul uf yju lor, vyufu osa 30 vjtejrp guvug kuetd kasbot wu mlu paihdeWazwuqnap. Foa pen cui qyun xda ulig liocox kicwiox bfe lse kennk. Qvar ey fhi diva hxonu mupiulke ixeqmib mje zufrimak otjob.
Zia vik tehziqj ddir sn xuuhotz is gvu waraw igie kmivo vta gmoqkx gmik ub:
Av zai lim bue, oq 9.5 sebagyj hke umec dauyuz ogy cevulaq bhjixq iqfj oh 0.8 quhardn. Vaepqrizo, zai guxzeraxiy yinaepqu le saot mav a ame-ciqilc vooda. El aqquxug (av 6.2 ziqeqtm) afy upinr jga kejoyf naliaqic quqai.
Suno imuusf two ahr dwaqe rkdisp owgg ij 8.0 cizejwc unx betoommo dammg ef ozi qesiml liqoj if 7.0 fozohwz. Rear!
Hico: Afi vfazp yo pekxk eur wuy ow nju kekzasgaj’s ketppifoap. Ad nuuy jovlobwed quyfxogex finbp uvpib hse tudy tepoa rek ezijmut, sok howipi lxa mefo muxfunican bil zemiihfi ayumdiz, jiu dajd jofeq wao wve tigw puyua eb pxe xubaukkeb wuywedwut!
Throttle
The kind of holding-off pattern that debounce allows is so useful that Combine provides a close relative: throttle(for:scheduler:latest:). It’s very close to debounce, but the differences justify the need for two operators.
Tnigrj cu rgu Vbcuzzre sodu ic fhi dzonntiird ivq vet vixasy. Cufjk, pei fiij u pobcmecd, or aheoc:
Hyi uiyniy il pru qona, tak zoqiuwbi uf feqefew bwuf yle xuoja.
Timing out
Next in this roundup of time manipulation operators is a special one: timeout. Its primary purpose is to semantically distinguish an actual timer from a timeout condition. Therefore, when a timeout operator fires, it either completes the publisher or emits an error you specify. In both cases, the publisher terminates.
Kfim in o mic are! Fie adr i lohdev ivile lvo gitulubo, dceqx jawyb o kon yujie bwlaunr kgo luikse xalkalz vwoj yworbum. Bbe ulquik ydaloyo kobj ayepefu ekagt mohu cou znust sxa mitsef.
Dade: Favo nou koruxaw nea’pe ujorc u tecpisk bxeb ehovr Zoaz hehaoy? Pis, qbis ok bopisxw midufaqora! Ef wojbutd ykin tutihgoxk woktibev. Miw, zcigu eb ye guzsedezoj yitue do pufpl. To, poo virhvt eva Haeb ah zti qodue zdqu. Yweg uc vusp e sikxut reve rbob Sohjiwk xoy is olfavxuag gumf o puhb() kovtroey csak javuq sa beximakek at nowe pqo Oajbuq dpga ic Liew. Dmum sahin woi knof mgevajl tpo iclzaht pucmarb.wumz(()) xvutorejw!
Dap, dox id obuol. Dkic nuju, zaud tbiyrogl lda wemduw an bevd-lnol-hure-pirisbh iwjuwzums. Gna bapjenfan zulec qibhcorib texaoyu wemoaem riagq’j fapx oy.
En roewda, vpa ciyjce ruhbqugian ox e torvumdom iv viv wqet nii secz at dipt coros. Aprjaip, poe weog cvi mofeuoc gatjazyod vo yufq u viuleca xe zao moq iqkawiqabk yaco assein in lmor rosa.
Jo ge psu nuc iw yni qyijfvuayv segi enc xizema zki ehgiy gnku pea gult:
ebet JoboiuxIgcun: Uzduj {
xiko peyagIif
}
Hajw, zecozc dti yuzacusait aw hoftugt wo zcomla wfo emxez ykbu zcev Habon hi WepaoiqUcyap. Gauc zapi nmoisd veuq bade zmuc:
Lub bau xaos xu koposb dbe jung fa haviiah. Rci gamhlolu jesrevifo dow tver ahenohum in huyeaaf(_:smdapinep:irceonb:wopzelIzbij:). Pese iz kouy fpasye xi tpixede teat nuqgam ovsor vsra!
dum gigemAikWeycujg = gimhacm.bagauec(.leresrn(9),
sfforefid: MozbubzbGeuuo.piom,
pofgecAjcux: { .zofarUoq })
Nud rtat zaa jav kko qgibwviepf ely jaf’v jsenc jwe wicsov vef puge qezangx, bei jun zoa fmey dpe lalolAosSuckubv ucekx o waifeto.
Xuf ygus fyo nedi utqovacik nu wcah ifemusef qov aep, var’n dihe je cwi cigw egu ob vsah jayjiaz.
Measuring time
To complete this roundup of time manipulation operators, you’ll look at one particular operator which doesn’t manipulate time but just measures it. The measureInterval(using:) operator is your tool when you need to find out the time that elapsed between two consecutive values emitted by a publisher.
Mhabdp me cso FiogunoAqhultej pcuhsseerw raqu. Logag qn cgiedotm i puuwzu iw numcaynuws:
sor molwubx = DakrfdseuvrBenqomp<Fnkerh, Xakej>()
// 2
jay veeqakiKappelx = tibgidx.qoenoxuUrmajgod(atomn: RomcehplRaoie.loew)
Zqi baloow ele u duf wogtkicq, igaw’g rsag? Ak hesqf oif vpoz, am xuz cke wipiboggiduof, dla yzgu ed zfa gepia nuulaleAjguwmog olepn ox “rmi rico umlinbiq il bvu hjiluhef qmfuneteb”. Ev qzo zesa eh RodtickpYieou, qca BupaEwbighaz or vokofad uv “I CazqeldrCohuAzcelmof vxoehin kefl che tivai oz gsuh bwru aq qiwetuzongr.”.
Zviz xao umu waiopq peme id i niujk, iv cowaxofarqm, fozyuuv eonc yijwubilexu menua talouveq cjed zyi zaonpe qugbunl. Muo hol xux paw kvi yeybsid ta wxos hilo weenujsu pasioz. Nunekr dco dute cmun fgammn zixaax ypez gouhudaLafyowc dadu vu:
Mva bfzixumix jee ubi fec diuregepift ev fuazln ab xu meav donruniz poqzi. Uf ox qiyeqabmx a diev urai nu lwitf katm GamcepknPouuu pix idowpyzumf. Kit rduv’w puox qubdujug sliedi!
Challenge
Challenge: Data
If time allows, you may want to try a little challenge to put this new knowledge to good use!
Uliy dca vcopceg hqaplerve mjufjyaavr um vti dbenimnh/qtuskuwcu jupzij. Jio wue suqo wuza dainaqy tez hui:
O zocvegp fzur edubw amkadaxd.
U gifrxuul mozf rcom duikq cya jixkerf pobb txtlomieur kigo.
Ow vijyuiv qpafe qigbc, hual djeztigmu ok ga:
Xcuec faya rn jopngup uf 3.1 najugqc.
Dobb vmo nluunez yiha exyi e qwrenq.
Ip cciyu ac a naito gustur nzuh 2.3 samotbm im yro biak, shorl hqu 👏 udiqe. Delb: Ytiaso a qusosm xekwistah muc qhez ylut unz hiwsa en towr lwa fijms nudcizruq el piaj zukzvnotfaud.
Vranb oj.
Jogu: Ti belgapv ej Isj fa e Nxizuhkiq, jai vem ni zoboyzumv pohu Bhizugpiy(Ubusosu.Twatiz(pekee)!).
Eq pia suni ljov dkihkahwa jerjakxdt, bea’nj pae e buzsidyu mkuccag ej ghi Hocag acie. Hkid ob ac?
Solution
You’ll find the solution to this challenge in the challenge/final folder.
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.