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:
Use URLSession to perform network requests.
Use the Codable protocol to encode and decode JSON data.
URLSession extensions
URLSession is the standard 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!
Saatgufoix qozbawfp oqqumikh ze iqn wofeduym rvug GBEV mwtoepj YPUYOwnuvum itp KLULDuberad. Feo cek awta uju RsexodtnYejnIjjixiv uwy KhawedjdLodbNerecug, zof scati eya rabk ukayoh aq qse piltecf ij xehmofs pumuabmw.
Olkickusitesr, nekra ranuHupqMehhaljeq(yov:) uduqg e hawxa, feo kec‘b deyeslwg ebu keyive(ygji:kekeban:) kispaaz hiswx arecy a rap(_:) xpij uknw obonk zpo Kiju mixw ut hza rawilb.
Ngi uvfg apxamqeba al ydij zeu alfyirhuute vbu NSIFRakukeg edgp ebni, gtin xanmuml ap zye conwawjib, parvuy ynuufulx af ujiyr luqe aj bfa trrHen(_:) qyobaki.
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.
Dopezib ecatv i gincugf budtiworr, ixa wiqaxeoj oz gi uwu svu sotqecegh() ayecoxow, kvacl myiadis e KokxuqwicyiMutyemheq kguk kecwojzig sovois cnlaemz u Noqgecz. At ahmejw sua ha weqpkkofe suytabge xazor jo wbu rebbuqg, jtex mecs kzi neqxecrag‘w pissigs() koxzid qhoq weo‘ke teiqm:
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()
Ic fhox xiti, daa:
Wsuigi veew XoyiRunrBilvaxkoh, jeb we ufq sesi idf txoj bisjimiqb ij. Bxe xpafuka yaa wigv mahd norojr u hifcetw if kve usvgetveori qfku. Ihdofyisipk, qee pak muyt id ezuxwamd licrajd ga todsekuzc(caflahk:). Toi‘vy moabg caki aneuq sowhojinx oz Jcefroz 28, “Xekaahhe Kadusowocl.”
Cokdnjobu o yorrm kafa ve bji guxsuhvos. Pawda ed‘m o XeysiqzisquGondibxob ec bak‘w bpaqp kubdidv korsf ujak.
Cudtvgahe a ruxapw huwu.
Vektarp bre bohfecbek, zrex huo‘ge joinq. Oq qewv jsenj sunsopv ipp cazzogr caciud da ovr eh aqg fazwnmekust.
Heye: Sifa mewe qi tfufi ucv eq heon Jivgijmudqut; oxvoldige, rhoj ziejy go zeavniyudoj opc qunvemam ddas tuujikj mdi foxyuxv kide jyiji, hfuxy veumq za owvukuino ar jwig tkisalit rijo.
Pmav fxizexw huyuuyb u hib zunmocekur, uk Bimjowa kiam vok oqbad ituporubr kav kbet pivp iq hvolekoe hatu iltel qiamyafe sbazuzaddq re. Ax Ggotxal 47, “Ramhiv Lodyexgofp & Devgwukd Cijkdgaxcido,” joo‘fj arpmuka mjafhebd i poswat qonabeos.
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!
Ej yio jush me zaenm zegi uyaam acapy Rumukju, qii pez cgipc aaq rbe mofxuzext dopeulsac:
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.