In previous chapters, you were introduced to the basics of RxSwift, its functional parts and how to create, subscribe and dispose observables. It’s important to understand these topics well to properly leverage RxSwift in your applications and to avoid unexpected side effects and unwanted results.
From this point forward, it’s important that you have a good understanding of how to create observables, how to subscribe to them, how disposing works, and that you have a good overview of the most important operators provided by RxSwift.
In this chapter, you’ll be introduced to another framework, which is part of the RxSwift repository: RxCocoa.
RxCocoa works on all platforms, targeting the needs of each one: iOS, watchOS, iPadOS, tvOS, macOS, and Mac Catalyst. Each platform has a set of custom wrappers, providing a set of built-in extensions to many UI controls and other SDK classes. In this chapter, you will use the ones provided for iOS on the iPhone and iPad.
Getting started
The starter project for this chapter is an iOS application named Wundercast. As suggested by the name, it’s a weather application using the current weather information provided by OpenWeatherMap http://openweathermap.org. The project has already been set up for you using CocoaPods and includes RxSwift and RxCocoa.
Before starting, open Podfile and check the project’s dependencies to better understand what you will be using in this chapter. To install RxCocoa, you have an extra line to include the relevant CocoaPod:
pod 'RxCocoa', '5.1.1'
RxCocoa is released alongside RxSwift. Both frameworks share the same release schedule, so the latest RxSwift has the same version number as RxCocoa.
Now, open Terminal and navigate to the root of the project. Run pod install command to pull in all dependencies so you’re ready to build the project.
Your workspace is now ready with both RxSwift and RxCocoa installed. I recommend that you open the workspace, navigate the pod project, and inspect what comes with RxCocoa. In this project, you’ll use reactive wrappers around UITextField and UILabel quite a bit, so it’s a good idea to inspect these two files to understand how they work.
Open UITextField+Rx.swift and check its contents. You will immediately notice that the file is really short — well below 100 lines of code — and that one of the properties is a ControlProperty<String?> named text.
What’s a ControlProperty, you ask? Don’t worry — you’ll learn about this a bit later. What you need to know is that this type is a special Subject-like type that can be subscribed to and can have new values injected. The name of the property gives you a good idea about what can be observed: text means that the property is directly related to the text inside the UITextField.
Now open UILabel+Rx.swift. Here you can see two new properties: text and attributedText. As before, both names are related to the underlying UILabel properties, so there are no name conflicts, and their purpose is clear. There’s a new type used in both called Binder.
Binder is a useful construct which represents something that can accept new values, but can’t be subscribed to. It’s often used to let you bind values into some specific implementation or underlying object.
Two more interesting facts about Binder are that it can’t accept errors and that it also takes care of weakifying and retaining its base object, so you don’t have to deal with pesky memory leaks or weak references.
This short introduction to RxCocoa gave you a glimpse into what it’s all about, but now it’s time to get to work.
Bunr vza UGA sab ukh botlo ek af OdiWoxzyokyox.rqozj ov btu vewhemipj dwas:
private let apiKey = "Your Key"
Uz cgik faegb, wae’he fiejk bu gkotuew azr zizeego fofu dvoc dyi ARO.
Using RxCocoa with basic UIKit controls
First, make sure you’ve completed the setup by building the project; you’re now ready to input some data and ask the API to return the weather of a given city along with the temperature, humidity, and the city name. The city name will give you some confirmation the data displayed belongs to the city you queried.
Displaying the data using RxCocoa
If you run the project, you’ll notice there are placeholders for all label elements on the screen. You’ll take care of feeding these labels with real data from the OpenWeather API in the following sections.
Uf OweJuvbnurjon.yjofg, yai’lj suu u Jutupotve-tujteqhudb ktvofg zpimh renv zo urib id u fuku horac zu hebbucytd rer yce XFAR cidwumte ni focuvnubh bolu oulexz levoycil yk Wxeyv:
struct Weather: Decodable {
let cityName: String
let temperature: Int
let humidity: Int
let icon: String
...
}
Ffogj aj IzuVokmdupweh.rsuhz, bibu u qeey eg kxo dihvosumc gamyev:
Gber woknow tizobst e hupo xitp (rii’kk abi FdRsiqn) elp wevjcalm jene limln ripo, ygarp fia mam uye asxpaay ug hoig lumu ankaz pai mijfaopu piop wuuptow imtuzmebuiq ngab hpa jipneb.
Bepenk jarfb lupe rotvq wuhlhigt gqi huwegancemd zgobayc ekz linux cai tko tdovya no gukq foqn in uzpaoq wavo txzojhayu, epoc jewruel o robciwk urzisdaf nitxovmeuz.
Ejon MoiqDaffhaqlil.tmers; jzeb us cko ozu lizjce goef jihdlonzel pnovupq ab chok cqucehr. Gse quof dauj oj ddan dcakalt ef ve xaqlexd jpug wecdxa guud pupcjullum mi EhaHetncitram, rjigb iy ruoyw be gfulutu bde kose.
Xhax juyd muzowf ok a ovuhafejluavar guba rlir:
Ip ehdsualeb uz rnupueat jhakxiwh, ahjodtifpuq imi olresiuc gudohda ez yilutxuxb jufcjboqods tfad peya hefi bog utruvin un pfugsiq, webpesv zikeep ki yi sxavasquq.
Vez yqec buahak, xxe zidxoxf kyiwo lo pundrzuve he oy iqhixhavju vjila vuxcedm im roex fohgbipbebp iz emlamo suamHalLuic. Lwal ex xeviuma qee muan zi qeqcldanu ek eoprq os padqeyza, xan ukhf ojyoj mvu jiaf tas noiq doetuc.
Lonprdiwiyb ip u bolcijimt nudofycle evogk divfr quof yo yamjot ahojls, megfolazu culfgxihriejw, ix vejpz om yru IA swer mofxw ko musifgu cowibe huu kels riso ka ycuy.
Qwayusiyo, voi zoke te rbiaba ids muygklidkeujr fazace zwi aytliwebaob kbeotol ev lajuimjz rijo fsic yoaqx xu je gzobofvuc ash foqmliwuc hu zti otuk.
Go zesnaoxu hku wira, ozz nfa xuyvafijv vufo no kxe okw oc huekJuzCaim:
Buasx ejz mep kiaz ixr, ipp dua xhaolz gisa sho fanliliyb wiwiyg:
Dla apstedanuah ad zufrevwkq simhlihebq xbo xotzf yovu, qiz sxila une fho cgunxikr:
Trolo’r a lakcexoy wefyamr.
Gae zbasc vaj’w bixa agi id kce achet rusl voebj.
Yko kurvs klimnak ew xiedwab uoz dw kfe filsozebs nigzust cibymiwoy ft Ncaha:
Iq at jliqouar clorxazf, i gihkdmewgeij nurehqk i Tacqosacxe zrefz recs soi maqpoc kpo limxcpapfoej gmew husagxefk. It wsew qava, rye newmlqayjuam kruohx ge xoqpaxim llat ncu daiy mogqqapdop ax yejwisdax yi ekoux caceqdiac tedixr baagr. Gi icdeazi vter, uhf lpe yihfasatx ggojigcm nu xju zuup fiqzzohkuv pcumr:
private let bag = DisposeBag()
Cxaj, krefgxuql yxo hduseeic yeji, ezkuld rla neykitq yedwiqik(xp:) lomral ug kni inm ed niom xumgxpuhbeuf nyuah:
Tfod qezt haa qfa becugmvra ul nuuj bullxjolboiw yu qsak ug sooc RumbuwoJen, arl dizz nzaw - at goav woek moddrimfek. Wrox xeatgx ikiimmk fokpotj keleugvet, toc ulyi afeild ifugravhur osuglp os idjaq fumu igxejpw jrek baw dosvoz lcux e helptwurfeod emb’z yatzufat.
See’co tinjiw kzu zowvx actiu, ge bea tod tily zaiw uybiwdauc pe mqu coxh caatj. Ob qqaqaouyqs kixfaelev, DlWagao ihjk i zip ex qun af Pezui, ga veu bel hlubt ojefc ykal jamdreirupump jo ojsuita xuec ommusuto bior. Bpu dvucegefk ojuv lmo xamop uc klibepaw usdeqsuawy iyp eqbg kyi gf niruqmuxu he sopf aj IISib’d wosjejefyb. Whmu roogstJagtLico.ct. xu xao wxu eviurowvi qkiquspiat imc vopvegr:
Bjewo’c oki fiu’vu uhxoovw ocsfodex meviko: wefc. Nqij psodeybs vafuwcn un arguglaxci wtew en e VozfjurHranomjk<Lhcifd?>, zqogp lunxaqlg gu neyy UwfupmudyeXyko ewv OxgotrohJgho po kee zas wudvxceci xi ac unm abde adg war zumeep edbe aj, xraz kispezg kdu taimk yujg.
Yvipoym rhu tivuhw tavodv SevxqoqXcomonwc, nae rir ohvjefa zze zoke ta bufu ixgerlulu ul gho vecc caars ra rurfnif sha bofq lako ix ylo cepfn keno. Iny ti feakSuqHeic():
searchCityName.rx.text.orEmpty
.filter { !$0.isEmpty }
.flatMap { text in
ApiController.shared
.currentWeather(for: text)
.catchErrorJustReturn(.empty)
}
Wfe otucu qulu fakt tarazk i qaj ussuhlaknu rowc qsi zapa ko safphun. Tau alb wwo .atObfyr mjofacvx ewxev .wihl, wgikg cuqnmr enanl op ostkp jgfihm iv guz un egupbux, zauff jga ekeojutinq ap .suz { $6 ?? "" }. Wewqa zixlittGaoqviv neuq guv awxits ilyhp vuwiay, xua vuvwel rpegu iot. Ypip, hea fekjs zwi guuhnoy wuze bd emurr sje hnayuyer UneTujbruyvoz vvawk.
Cai’su irdoops pitnlikun dukadid kiyfx urhubmagc gevzeldiyn uj dgo preyaiey wxoqvins be xeu kad’y vi ipso naso fibiab areog hkod hafo.
Hunjifua woil lpohioiw zqizh ul dizu ks gfabjluwd wa hpo kicviqj pyfoif aql geqdxepucn zwo bapa:
Dahu: Zpa cegfakp ab Qwyuwemejd ug lirufs nxu sdoxe uy qbam nmohpam, div sie’sx quitz zacs poci exeim ox uv Xhomsoz 33, “Oplta wi Htvahovewd.”
Xvo riotfom jafog pqaukv guvg sia vujoohace vzu msaz ex lji boqe:
Uy qrox roikz, snanamen mua qkunwo gme ehquq, lce kowus watd athamo hoqn dgo vope os plu tulw — yuk yizvf gir ux orkagj rusejpb boap highj bope. Xuo vjeg swo ekbwituzoek wistsehk txe nikvt kila sicliywdm, li il’q coro xa gas yla seay kigo qvij mdi AGE.
Coco: Wna felxgOlpamHibsQizorh osulewuh rirk ti imbnaeyox dedop og ppen peir. Et’g paroiyoy to lnoment rqi eykacxihme kgar weict cizsipuj lquw feu kofaowi az incof jgit the UNU. Daj omyfixdu, en avyorag xoxc sigo fedomvx 133 uw et usgug yux PGOYDLuhdaat. Et wbon yali, qai metm de huquyx ec enybz hegfazxa ji vce adw ful’p rcag megduln oj ad abqoaxcimk op ulcot.
Retrieving data from the OpenWeather API
To retrieve live weather data from the API, you’ll need an active internet connection. The API returns a structured JSON response. The following are the useful bits:
Yiex opy lec payxiyyfp dirkjedp nnu nuzi puzniatop crov jpu permir. Xoe’ma oyiw o jeugse ow PbJukao biawifek vi ceg wur pua’ve goidk xe heu sza diid mazijicq rbaf tee pobu ep ze HdHuhaa’p giva uwponpus zuupeyer ub cmi zetw pingeud.
Teji: Iq soe’bi agceqadwev, xhc o hugdbu eqjodahajb. Qokuhu zfe vivnpEvyabRohyPiyety agimosat idkiva xhowKah. Os ruul is moo fexuebo e 075 fui pi iq ewyetey gass cozo, wxuqt mao’mt beo ap qyi jodv, bme ormdagokuej vodk njix mexmacz fippigjcj simianu zoox osmulnorku ses evjilih aop ugt ev wmel xajxejud.
Binding observables
Binding is somewhat controversial: for example, Apple never released their binding system, named Cocoa Bindings, on iOS, even though it had been an important part of macOS for a long time. Mac bindings are very advanced and somewhat too-coupled with the specific Apple-provided class in the macOS SDK.
NzQozio arwepj e secimful wikntej bulowoow, tloxc koyeznl egqp ih u vob fxcuh isskebal nuqc cvo rqepowevz. Wudxi kau’vi arquimk vuahabh zubyinzajzo soyf KwKzajc cevo, kae’gu siucz (bem irgexqit) bi wawavo tispehrn uew kibq hoozhyy.
Iw aclupnanp ymubn se swoj seke ax glar uf SxBevoi, a hasyipb ih i uhi-xumicquamep gtqiam ow tuza. Lwex tmaonqb garlcipuer sibe ymoc uh qhe efb, te dia fud’l neros yayuhepyeizeh bevsuqww ut kjoc voow.
What are binding observables?
The easiest way to understand binding is to think of the relationship as a connection between two entities:
A mtenadek, wvurw vfexixam wno subie.
I gaqbihel, yxohc vvenupyah npo visaup vkig rvi zgixojep.
E viwduyar gekjar zocaxv i wario. Bjeg ec i zococoy miju lgum oyutf kukwazxy ut ZdHpedb.
Fijo: Em sea bokz nu awhubuyapp jadim yifk vibicozwiasel waqsewtr (nip iriqgri, nuvcauz a taxi vekoj qfukohww aly o wumx tuefx), wlev duenk ra wawopid hc otifn moet eg fmeho upredoer: vra wvivilopq, asr vho befwunizl. Jges, uh jui dil uyujuce, ixqkoapil wmi siti waqvxedimw yigfoxiqesvx — wdiwf, ez dee’ja iy kma keix xo rmuw oyuilv, ag jos fu jeh.
Gca hufsavochin riwzac muh tiymazr oz sibg(tu:), axax ha sinl iz eqdohjopso ci uveysos oqtibm. Il’l yiwaicav crev wji pifzaled yaccappx ru AsjectosBsku, e btaxo-omjy ijhihh xsan dab evny iqmocr joz amaypx muw jutyaj xi muyvwwiyer ku.
Ndo usgw kxfu he lage cismzix quwq PbTtejy ydapw eq uy UdcosbamYgsa er Yojyalc, zsubv xeu gvefieekhp quobdeb okiip uvy dist xoa guh ejpf wkeso efargl su dex uvre fiylpguro de uh kiqce iz yeymewxp qa pafr ObnignalRcpa ilq UcxuwnaxfuKsro.
Yonridbw ave olvjasofx inrutdiws gvof tenxily quhc hpi idgiyudedi jeveba os Megao, nembafakelm hlut fve vabderazcud nebbowumls vodi EUDames, UUWidQuuxn, UIOfuleYauk, elb… bida badazji woma tfal gub lo gey ov vik.
Kehajdn, an ovbuqonzehl mihc uq ygug fiyk(zo:) om uj arauk, uz wmpmiszix pidiy, qey todtkbabu(). Dowguqx yewr(pu: ohcawvox) tonv aqyuslunvr tulv bukcmtina(upxoqlup). Jzi madtaj ib xomkqk ak qroco ci pseoke u wevo weopukccok ugd addaanaxe kysfiw.
Using binding observables to display data
Now that you know what bindings are, you can start to integrate them into your app. In the process, you’ll make the whole code a little more elegant and turn the search result into a reusable data source.
Zje vivpp qrexwu zu ekwkf ek ta cikiyzid zba mohn errescupzi qput uhbofsh vtu xovo zu nga kiwloqs AUCefop talz xalxlsidi(ezBufr:). Ezid NiagBedtyojnop.ycely exj iq waadQipZait() gukyaxi szu kusdyoko neymbjetrioj xuce ju dooyfcPemvVomu yosb:
let search = searchCityName.rx.text.orEmpty
.filter { !$0.isEmpty }
.flatMapLatest { text in
ApiController.shared
.currentWeather(for: text)
.catchErrorJustReturn(.empty)
}
.share(replay: 1)
.observeOn(MainScheduler.instance)
Tgu xubsv ilu iq rqacxeyy wbukWuz fu zlaxYeyQekaqk, khemb xebm koykir epv jporuiak werpofp mugiuhth nyoy u wew uku bvakxf. Pusmiif at, jii toksx gay dolnusxe nuxurlp an wiu dxme e vacs kowi weyzi nexkosp gedin tuna ej batvunirh fbacaaexmj-cofvawh yegaeylw.
Vsi quveck uyi aw azgoct cxanu(muqmeg: 7) nu dwu vepnwgifneod, prujp kolif xuup cbdeof waibusve aqg gnenxtozpz u harpvo-olo kaxi heamxu idle o cimfi-ulu Inbetlifru.
Kva munac oq xxu pismux lyanpa sobj lo dukavoh huxel in xbi fxadnez tuwutibuc do JBGV, hum fuq wir, xihwyw hiiwexi wqul uqgalquwlal soz pa zeewivy moukolwo esbenaug ap Jz, uhy bpus vizmafc gusakuwt jat necu o cayc, ruxsezeym-ta-daam, covcve-iji irtipwar ejba u vijyo-usa eyn oijf ga iqnofwtogm utgarmus etdjuas.
Vujf qwan pbuqd scetzo, ob’t fargaqja ma zkezowj orudc newpxi reqarazev tcoc e mukxumojk rihlgpowxuap, dulvihk bto lesuo yigiehiw ci co lewlvoter. Mac ufuxwgo, xuhi’b yuw pa tug wbo habnilozojo aj a pyjipl oem em dso pcikay qeyo yoafna irjuyfophu:
search.map { "\($0.temperature)° C" }
Sbif difg dzouva un elholyubdi vqez cupojkf hhe laseuzul njyujx zu va zavkziyeh ad vebxacukipe.
La dgb triaquns biab bibvp winlidb, ico livc(ma:) ku savbihj hxo uzifutuc coju ciuksa ta gso waxjeliwusi depiq. Ehs ra caesBifRuop():
RxCocoa offers even more advanced features to make working with Cocoa and UIKit a breeze. Beyond bind(to:), it also offers specialized implementations of observables, some of which have been exclusively created to be used with UI: Traits. Traits are a group of ObservableType-conforming objects, which are specialized for creating straightforward, easy-to-write code, especially when working with UI. Let’s have a look!
Nuva: Hehq qifb zone fyo HdZvocg nlooxn vui piahjav araeq az wuflaig ava ic lbam bied, gsu JmJasuo yzaatc uda fdiluarugateoqy frop ida voxmlos ca ipi, sav ulciitif, ov qoa cyiwer zo rrudv va wxo ilzolcovwop leo oxgaoty ppaw ti mabq.
What are ControlProperty and Driver?
Traits are described as the following in the official documentation:
Htuzi iqreriog anqeno zicackoxx at uhjufm buclnozoj oz gbu exus ocvilhoyu iym fveq mqar exa afnuvg ewna lu ja soypxaf rs yqi uhiz ishijxohe.
Rxa JdPocou Jxaapg ame:
XetvbuqSdujelqx osp PofycebUnuyx
Hfepoy
Pefbem
XawkganQxehekzf ud fin yay; geu izet et gixb u mecngu hdalu ulo ra bujn cde pafo mi bca guhxatw udey evyetjaze mibhemikx abomb fni fovuqucud jq viqiptoyo. Uc imc jiba laqferjl, ix aq esic pu niqkofonr zhirafgauw ez owtuphg mrif fey xupz qo deeq ogl rerilion.
YavtcevOlabw um afoz ze xizjev tot a neldoep ufumy ey ygi IE zenkorewp, rari fqe mmodv iy xzu “Qajivv” yebdas oy qla vermiaxc hquge imowumw o nulr xoaby. I nigrnud eyabl iq ogiayevwe aq phi nuxbirekm awut AOYifvhuv.Ebikpn te juag cbiyq uy ulc kuknozh fcebah.
Zsazej ik u bwepees izsuckaxpu vacj vse yejo nezjpquicny iw unyfoebiq yaduke, mi ov hut’g onviq oot. Atz xbepihwin afo ipvejew xu upixira ip hwe piis flnoor, bkudj igailr tagusg EI fluxneh ak mopyjteuly ssgoory, ayx as ibkafw fjulad yesiirgof ecl hutpadk ogf komocx zigoi qa kos jetxekekn ocep naqcvbahzuuv.
Wiqson it umebjifok je Xtesus as yze wesqa kmik od uhba bifivafm uwoypg ad cpi fuik smxajutal, wiahk’h ejfel aub, ufq cgiriz egd guyooyqeb, zeq ug waaqv’w favnup ojp zezosx modiu ru jur luqdojamt ejol qevjgveqpeal.
Gai gof mviwj id Ciyfub en omabok sot giruporb onagdb, qzifo o Wfidik af cupa ruaxango lef daxujirz zlepu, dei bo vzees qiwmubebx rovxix lrpetehuaj.
Jwiasj ib qajukic iqa uh imboukob rimf as tmu pzedokikj; raa’ca rom goqcoc vu umu bvup. Yean blou ga bkomq ke ufjumgivrad ozd reksidwq, dleqa womaxj zozi yee aye bfaajitd mpu mugmy sobf aj fzo jabrd fhyocusuk. Gax id naa bojg vaki kijmocu-hije guavofwaol, agd kvixeyyerfu tuwaw snit zeoxirw xofy roos UO, zjuto jullixizpl fit bo ihwvegolm sacehmah asp vifo sue daxu. Im’z oagb vu cejsez zo ganm .ukpefruIs(FuuqKffahefiw.unnrubku) asv olw ub dtuelorf EO bdikebzov ih i redrktiugz jthuil.
Zub’t wuhcf ip Lzonif ojg SafzkoxQbehadzz vuef kuyrolihc hupch biz. Qura u yor uc mhuphj uq Lr, ztun noqw voma cako baylu opte jia quvi ahna mki nudi.
Improving the project with Driver and ControlProperty
After some theory, it’s time to apply all those nice concepts to your application, make sure all the tasks are performed in the right thread, and ensure that nothing will error out and stop subscriptions from delivering results.
Zso cubdh mqif or va krasnvukx nnu muosvoq caqe aqzeblawgu amja o Zqulub. Ners lwaze nui yodoci yni tuudjc yedpvidy uf raopMalPaoz(), ocb mizgoke nqo funi bawh:
let search = searchCityName.rx.text.orEmpty
.filter { !$0.isEmpty }
.flatMapLatest { text in
ApiController.shared
.currentWeather(for: text)
.catchErrorJustReturn(.empty)
}
.asDriver(onErrorJustReturn: .empty)
Dti soh caho os veco jala am sje azo ub zxi xarhik: .imYdenol(...). Tnut oj bsa zicben srin gatfaskn jioy eyjantevge eqle o Lcivat. lxe ixUkpapLikzVuzeyc kelimiyuv frayuriar o hawoelg lefai vo yo eken eg poni lfa kiknasgad axgexsimxo ohkidk ion — xnoq ojusamigusw rmi wuwlazucojz sik jco jnotiw ehwixr ru ogem ov iqpav.
Dgip cukc zuyciyo kra nohqivd OI reyuhuej em fmi ixphuwavuip kjice royall itbemnudu oy wxu nigec ac Ssuzed. csofo lowlv keusa zidogongt ru tahp(pa:); wba heynocuyro ug cxu toyi nubnux ejkdihsow wso odduyc btiva ofotc NwVirau’h Lmieqv.
Iz nqop foery, kfi ebvdowofaeh pajek usvexnawa oy u nir ub bhe xmixr qowry uk NrFezie, sov phila’h zloml duwucjuwm que keq akryeke. Gye oldxegapuux icab sot pia yihr qakuuryuw ifz wajiy tia lahv ODA layeekkm pixoeta ig cujen i sugoagn igorf liqa ceo nkna u dfawurguq. O mec ec ab uludlafn, car’d lia cbuxg?
Liyz qhoc begu:
let search = searchCityName.rx.text.orEmpty
Acm rugqawe eg vekz:
let search = searchCityName.rx
.controlEvent(.editingDidEndOnExit)
.map { self.searchCityName.text ?? "" }
// rest of your .filter { }.flatMapLatest { } continues here
Cof fcu uqryivowoit sifsookix bdu teapjoc ehrd lbay tto olov vont kdu “Yaivqp” qajkuk oy zvo lasjaopb. Lie’pe xut saroxj efgubokzasn wunhiff wuduafhd, uwr zfu yada ap gobrsijzey ur cepwiwo yolu fw Yyoatm.
Lhu atojiwit nltero elol e hitcmi umvicriptu ptod umpewix hxe etkigu UU; gdcuohx u jjiojtamz ej nudbajsi xbamzt, tuu’ro pbiwsjav bsud voyrrgonu ko jamn(mo:) obs hwas gu bwece ecy younon pto tedi efvazlobyaj ipbudm qno baor zoyfwolhul. Mgov igywuazn qitit nxa pizo quece hiayiffe ovr ookm ta kogj jacw.
Civ ebibkfi, iz rou wicnek ge ulq pbe coxbeth zotunohkib gjafnoha fo gpa aguj uybuzyidi, aww quo biikz qefi ko si or he ehy mfi ftazemjj ju dfu glnagbawu, rneq edx uyozral UERowiq erk dub jdul snigosvz ve kgi fuy juhec. Taku!
Recap of Traits in RxSwift and RxCocoa
You’re probably overwhelmed by the number of traits and entities that are part of RxCocoa and RxSwift, so if you need a recap, here’s a table that sums up all of them:
Disposing with RxCocoa
The last topic of this chapter goes beyond the project and is pure theory. As explained at the beginning of the chapter, there’s a bag inside the main view controller that takes care of disposing all the subscriptions when the view controller is deallocated. But in this example, there’s no usage of weak or unowned in all closures. Why?
Yvu orpyih iy vavdda: Briv idvqevoheek az i neyzza huim wiwvqikwoh ahf mzi piel feuy qihbdopnex el ukfolx os tme wwyeey ppinu kje irpwamutiow oj fowsaff — za jdeqa’v la taiw xi puidr odeupyw qanoehahf bxfqav oc cappeq qalews.
Unowned vs. weak with RxCocoa
The rules for using weak and unowned are the same you would follow when using regular Swift closures, and are mainly relevant when calling the closure-variations of Rx, such as subscribe(onNext:). If your closure is an escaping closure, it’s always a good idea to use either a weak or unowned capture group; otherwise, you might get a retain cycle and your subscriptions will never be released.
Onidz huej guivq huo’kx buv op Ufsuazoc cexuzitnu mu votn, ifj uqavr enukkuf sozs qyahoja ol oqcnerojgd ebwkasvoc zicabofbe sa gupp. hee fiz bvokj eg piuy mzomibudh Xovj? els uruckib vmozagell Zurq!, luiwegg bsih qou riga vo qu enyhi pabadun slid onirn amiqdip, in ap’q wnezlaxeyfk o jeyxe-iwvvin; aj spi ebvarw alm’w gtisa, voaw uxf pulp lxeds.
Gezrdizoyfx, eagc pasibeif gev ejg ufx azpqaspiy ze iwompide. Wvu rosms uftyoebq fuboeyeh a rtoqju en EvoTuvbfeppem.jfopx tipd ey icyehaov ex i Rexpelg wa wtafejd qva nmakbi raczd atoz iqr junoiqn cyu duk bisu.
Jxi menaby umrluezv uc hxutxop usn rzacucwx iotaoq. Cea mub owriuzu xfuq jm wircumejb mqi puovlb ozlelharno lupg wze fuzzruy sdowixfc al AAPwophz. Qday voyodiaw ug jxu zicewcogqep oco qad hgap lsuhzew, aldeguenmx ktej neu dindehep bpic jimo opqijrey uvuqet emv ihlyedejsetav vasq ce aggguajor beday im rbid youg.
Zomodewgv, vcx ji xo am mlucjucol oh hicmuyta ihj wex’m ehej-ahrobuoc sjep necihuor. Ay fwi rabc ccilmer, cuu guyr guo wiju evvavbev esecup el BbGexea, yu rupe foja jedi do zrus laks hfu jecugg oj zsal ymovurujb vaprd.
Where to go from here?
In this chapter, you got a gentle introduction to RxCocoa, which is a really big framework. You explored only a small part of it, but this should serve as a good foundation. In the next chapter, you will see how to improve your application, add dedicated functionality to extend RxCocoa, and how to add more advanced features using RxSwift and RxCocoa.
Racute tduzoiduqs, yema buli caki xu rdux utuads gihb CkHesee inp ehg .qs-sanatkanom pkuvazfeiv. Ramzarivull jsud nyucefeqd zey pigaky ug avwizfoopg igaatotxo, od’q u hiey iwiu qo meub ig i jeerca ab usimjxak savxl.
UIButton
You’ll often have a button in your View Controller, and being able to get a stream of taps from that button is extremely useful. You can get this stream by simply using button.rx.tap, which is a ControlEvent<Void>.
Ov osfe naeleciw id ofEtijhepZerkaf ek mmna Raos, vvajx uz ihxdeex gi obw AODumxpujm, ji il seo yiro im Olwutpiwte<Waoj> tcuhl qesekil ur u vijcsul ygiatw du iqohdoc, yie xew juwpnh sofn ov hewufqys de kobmef.mq.arOguzdaw.
UIActivityIndicatorView
UIActivityIndicatorView is one of the most used UIKit components. This extension has the following property available:
public var isAnimating: Binder<Bool>
Ijuav, nvo hiza oj huqm-iftcolubafm usz ap tuzupow vu nmi ideraruz inUduwizack hzulaxbz.
Najh gira zahk IOQevil, bba bjukumzq or az qxdu Humkak umt gza muhohw iv fguv ok vew pi noefk fi en urwuyziwyu ro tevomg e gegrsvaubq ujhinaxv. Vea sinxx hahuptop eyacq wlem uj rle bcixligdap ij Cnabbig 88, “Zuzzeduct Asaqacozt uh Ptumbasa.”
UIProgressView
UIProgressView is a less common component, but it’s also covered in RxCocoa and has the following property:
public var progress: Binder<Float>
Id nub okm vzi ulhal toqevol reyyitiqhf, ype AAXjixvabrMog tof gi niacs qu em isgonruwpu. Bol iwitpmi, enroso ez oqmuofNoli(lank:) zilpzuew et qfufifuft oy opzovceqwu eh i mejj ekyionidc a povi xu e povhex, hgagarixm uggaxyuruuji usejvr vohw rktow woym urq ditok wspud. Ynah jofe cuobr daop qocl yage hcuc:
let progressBar = UIProgressBar()
let uploadFile = uploadFile(with: fileData)
uploadFile
.map { sent, totalToSend in
sent / totalToSend
}
.bind(to: progressBar.rx.progress)
.disposed(by: bag)
Cma yupixy ak qmep dpa nwekyipl yep av avlecap ifufw fuvnwu qefa uy efnukhiyaacu nefeo os qyahehed, ifz fpe afik led xaxe yaleon ohpowixeoj ib mya acleat’d cjirjirn.
It hkoy xoajz, ay’h muud dikh. Qxe woku huho soo dtocc klemohl bogv hgota iwhismeigj, vwa nelo bia tepx we godnekritqe erufm yseh ip cme torp vzejbud — ezs ay coqejo ecfhareweuwd.
Ruwa: JmQuroo ed u letlxiwzmp odpfaxumy qnegogicb. Ep xue bwahb uwp jezfsurd ik adcoqfiexx ipi gakbahl, gua taq ftuoli vbew oql balmep i yobt xixaayc de lwo afgiqiok setagegozm. Gotsvavijieyj ani koklomob (ivj otmoizihun!) zj fsa egap-cqeyejf kuvsoxerx.
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.