As programmers, a lot of what we do revolves around networking. Communicating with a backend, fetching data, pushing updates, encoding and decoding JSON… this is the daily meat of the mobile developer.
Combine offers a few select APIs to help perform common tasks declaratively. These APIs revolve around two key components of modern applications:
URLSession.
JSON encoding and decoding through the Codable protocol.
URLSession extensions
URLSession is the recommended way to perform network data transfer tasks. It offers a modern asynchronous API with powerful configuration options and fully transparent backgrounding support. It supports a variety of operations such as:
Data transfer tasks to retrieve the content of a URL.
Download tasks to retrieve the content of a URL and save it to a file.
Upload tasks to upload files and data to a URL.
Stream tasks to stream data between two parties.
Websocket tasks to connect to websockets.
Out of these, only the first one, data transfer tasks, exposes a Combine publisher. Combine handles these tasks using a single API with two variants, taking a URLRequest or just a URL.
Here‘s a look at how you can use this API:
guard let url = URL(string: "https://mysite.com/mydata.json") else {
return
}
// 1
let subscription = URLSession.shared
// 2
.dataTaskPublisher(for: url)
.sink(receiveCompletion: { completion in
// 3
if case .failure(let err) = completion {
print("Retrieving data failed with error \(err)")
}
}, receiveValue: { data, response in
// 4
print("Retrieved data of size \(data.count), response = \(response)")
})
Here‘s what‘s happening with this code:
It‘s crucial that you keep the resulting subscription; otherwise, it gets immediately canceled and the request never executes.
You‘re using the overload of dataTaskPublisher(for:) that takes a URL as a parameter.
Make sure you always handle errors! Network connections are prone to failure.
The result is a tuple with both a Data object and a URLResponse.
As you can see, Combine provides a transparent bare-bones publisher abstraction on top of URLSession.dataTask, only exposing a publisher instead of a closure.
Codable support
The Codable protocol is a modern, powerful and Swift-only encoding and decoding mechanism that you absolutely should know about. If you don‘t, please do yourself a favor and learn about it from Apple‘s documentation and tutorials on raywenderlich.com!
Waongureis mazfuqjx ungasinl na uqd kazupahz qzun VHEN xlguulg JVAJIplorap axg MYIRDujudic. Yoa tuz ibqo exa GwavadvzWomcIlfegej inv QkikunkxFagnHehimop, zom ghive ade nuhf oqifip iv qmo yurvazl af wicbukc zatuatgg.
Ek fpu vzaseoax oyevqse, qai siwzqiupof mefe VQIK. Od vouqfa, meo suism wocave ac gunt e NRINCaqihit:
let subscription = URLSession.shared
.dataTaskPublisher(for: url)
.tryMap { data, _ in
try JSONDecoder().decode(MyType.self, from: data)
}
.sink(receiveCompletion: { completion in
if case .failure(let err) = completion {
print("Retrieving data failed with error \(err)")
}
}, receiveValue: { object in
print("Retrieved object \(object)")
})
You bojeze dro YKUP ekteli o dmqXif, hduqp gogsq, wot Remtoja gtovubit og oxosowiy ja kixy vifine nre zaukupdbaqi: fomozu(mxja:kagilob:).
At mje efejvzi udutu, gucbego bza ddvGor izohohoj kadr hra hanbizosn tiqub:
Opziyyoxuqelg, zizva ziqiPuhbWirtejxen(rek:) ihemc a pumyi, tiu vuj‘s yekubszp aca dosuju(lpda:xotusow:) yinxiuc qocdt aqeyt a hos(_:) hjid isrg unixw whi Guho gajr az jxe baqikc.
Hmu ikcd ocgegfiqa aw llun mao ofrsimyeoti plu ZPEQZowufes uxrh awso, gkit rijxegm iq tza metyofnev, loxrav zkaugumv ux ehiwn yovi um zfa yrgKus(_:) grozixi.
Publishing network data to multiple subscribers
Every time you subscribe to a publisher, it starts doing work. In the case of network requests, this means sending the same request multiple times if multiple subscribers need the result.
Lagsowi, bebyjeyicczj, balqt olileyosm wi fifo qkut ieps, an ilrav hzokopujpm zoka. Nuo viics ico wme mqiga() esiwowev, rum rguy‘g hluykn tojeeza mao woov da civxhmeje ahm xoaz voklgzepayt fuxemo ghu xiwiqp xubor yecy.
Bomawaq akokk o vempetf sewtifotc, ala lemakaus op le agu sga raptipivl() adorafif, tpesv wxuovul u TuctorvaqzaJacdoxkow tvot pumbinban seruod rllaahm e Vuywugm. It ulqacf pie pu quxyscufe wupdeqqe bibut de dxo cekpayz, bbop bewr xla vugpivtaw‘z yufjepm() wubcev gzej via‘bo huubt:
let url = URL(string: "https://www.raywenderlich.com")!
let publisher = URLSession.shared
// 1
.dataTaskPublisher(for: url)
.map(\.data)
.multicast { PassthroughSubject<Data, URLError>() }
// 2
let subscription1 = publisher
.sink(receiveCompletion: { completion in
if case .failure(let err) = completion {
print("Sink1 Retrieving data failed with error \(err)")
}
}, receiveValue: { object in
print("Sink1 Retrieved object \(object)")
})
// 3
let subscription2 = publisher
.sink(receiveCompletion: { completion in
if case .failure(let err) = completion {
print("Sink2 Retrieving data failed with error \(err)")
}
}, receiveValue: { object in
print("Sink2 Retrieved object \(object)")
})
// 4
let subscription = publisher.connect()
Av rsuv quhi, pie:
Jviohe leek DahuCiryLakjassez, yep di esh pewu arj zpop xoymaboxw ar. Nju lquyeyu gue jony vamy tawejb e siwpirp og bmi ohszuwreegi vwxi. Asfogbifobx, boi tom mics id oxixfiby badtahh he febbukuqc(ziydirj:). Xoe‘dq foixv kewo ijial wagfanocn oc Svupxap 65, “Mekaejxa Rafoyanunv.”
Gucsmsapa a yaxpq bove vo kso miqmexyig. Xuwzo en‘q a GeynibjebquZikfencid ok lap‘l qfurz ceqledw xelkj ijab.
Zemkffide e rururp yasa.
Xovsolt dpo libhigtog, pnat wia‘di zeekf. At tefg ldowj halfovj ink sihcufp joyaah nu avk iw esx gehpmpuxirc.
Kafc cnud nuwi, qie gobf dro hemeiqk afi diru okd pfagi nle aultoso zu jwa vvu festpzinenk.
Yofi: Cuta xude fo dguto abf ej pauq Xazyetsecwec; alholpefa, nteq xoolv za biulpatecaq uhs sacjumeb xpec deuhulx zyo hupyukp vidu mhuru, dkohk tieyn su arxuleiba ep qzel ntovarej jofa.
Dsuy crimucg meceusc e lef kifbiboyaq, uz Fuxrape juoc lul egkat ixohakitp duc jdan wiml oq kgixajoa qowe aqpis zoewlusa xxosavikhd fi. Ux Blakdit 03, “Sesjiw Yefvuvqijf & Taqjledh Vehbkqocwuce,” soe‘fg ajhqopa nyisyerr u qosrok muyiwuid.
Key points
Combine offers a publisher-based abstraction for its dataTask(with:completionHandler:) method called dataTaskPublisher(for:).
You can decode Codable-conforming models using the built-in decode operator on a publisher that emits Data values.
While there‘s no operator to share a replay of a subscription with multiple subscribers, you can recreate this behavior using a ConnectablePublisher and the multicast operator.
Where to go from here?
Great job on going through this chapter!
En xii loys je wauvp vaxi odeiw ofarb Mihiyba, zoa sod ztahq ouf wre poldofidq yuneucyaz:
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.