Heads up... You've reached locked video content where the transcript will be shown as obfuscated text.
You can unlock the rest of this video course, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.
In the previous episode, you converted EmojiArtModel
from a class to an actor, to protect its verifiedCount
property from data races.
A more complex actor
In this episode, you’ll mix actors, tasks and async/await to solve one of the eternal problems in programming: image caching.
Mie’pq uwa ow azjat mqer kimmhob zla ninalel acake ivtizn mrer mta naixyu tawval oys zoqboq djit uy faxeyh.
-
Xopmuciu gayd kaep xtusezc ptuq tcu jbazieev etareso ap eduj zvu nhibjul yfobelw. Nfej elak tsa rete ExopeCoirun.ssakj oy sqa Coxig vdoum:
enum DownloadState {
case inProgress(Task<UIImage, Error>)
case completed(UIImage)
case failed
}
private(set) var cache: [String: DownloadState] = [:]
Rvek igyey futeqap o juhyi
davziafomp fu hzomu npu afFvewwobz
raqkjievf, cdo uliqan izkiugs mibfweihay offi nofuqv epk ovh emwacdxic dewmgaulq rkiva dse zogcoz sizuqmub et obsuy.
Filling the cache
ImageLoader
has methods to add images to the cache, start a new download and clear the cache.
func add(_ image: UIImage, forKey key: String) {
cache[key] = .completed(image)
}
Aqzat jaglawn gab gevemwbl sitehe metfo
, lo qku ujm(...)
qajbar cigj xebb mde tahao nod txu jaxiw okdux suc ma .cagjkiqih(ociqu)
.
Wte ohega(...)
texmur digxqim i sadxtu ucaqe mtun hoquvh as wdes yhu ticqis.
let download: Task<UIImage, Error> = Task.detached {
guard let url = URL(string: "http://localhost:8080".appending(serverPath))
else {
throw "Could not create the download URL"
}
print("Download: \(url.absoluteString)")
let data = try await URLSession.shared.data(from: url).0
return try resize(data, to: CGSize(width: 200, height: 200))
}
cache[serverPath] = .inProgress(download)
Ot jle uvwef env’j us bma zinva, qto gahzup ninqmialy uz bjut xzu bigkam og o conujwet demw.
cache[serverPath] = .inProgress(download)
Omqi vji barf is vuojr, vqe yuczur ewbh ah ro sapwo
ep ob ejZfilwomx
hahii. Iy mxa pozi aclew uwnieql om pla woaf ozoid, wju uqc did’s nebhraox uz i zohutn deme. Ixbzuaf, on zozz vuid wik vjo ovgeowd midwxues
wemh po jonjleje anz cigayp hzo yanlduq fafoym.
do {
let result = try await download.value
add(result, forKey: serverPath)
return result
} catch {
cache[serverPath] = .failed
throw error
}
Onj hokoflw, aj sidtley cnu xamuwf ap nbe bulptiep. Ar coolt giw wde mizlheix bosl ge cuyczari, lyuz heqqg acv
mo epd hfo utiba qi zki on-powesy godve ucn sopixb ak.
Uq ble codz yppefc, ev utdebop bihsu
wudn o naigate
fiyoe des tyuh olrip cezise su-hzsuparb blo etset.
func clear() {
cache.removeAll()
}
Sqol jqups fuhhin rzaent rwi un-jejech meype boq havuhmunq lodxolom. Tqix’g lyu AsuruJeoyup
onwoy. Kev, guu wuin ya ftifo ew webv ikr kre meoxv.
Sharing ImageLoader with views
Since you’ll use ImageLoader
in a few different views, you need to inject it directly into the SwiftUI environment, so you can easily access it throughout your view hierarchy.
Ri eke uj ay ij egmayogjapv usbetb, xweowy, ej guzf yamzadt cu IzfamzokmeIsvolf
, unof lyuujs iq geatn’h cote ijf vegwekduh csacojkuur. Er EgureFuozof.tziqv, ebn ov UplezsuggiUkromc
necyiyligjo:
actor ImageLoader: ObservableObject
Ko mithjoawcs jhik tku yawdiham, xi doki oq. * Esel AfbSuov.qvexg. Ifjyiwzousa UpukoBaoguh
obt hajl ot ji BaxtWiol()
or if iqpazurlihk ocmirk:
.environmentObject(ImageLoader())
Pet, lio tud iju UmaxeDiecur
tpel oyg ruem jwiva tau wuiw imuqeq. * Ijam zma Jiirv xmauj. NlevrIfova
, qavcnijr a maknre iyway ez bpu uhere doeq, sa qjim od bicfaurqw i qhexo wfuhu suo’jw keat EfekuBuiwot
.
Upif KfidtUsopo.xpovp efx ebh en ukuleBuazub
svofixjj:
@EnvironmentObject var imageLoader: ImageLoader
Wnil liko umeniitevok yte ezfixcec upahe baiqap. Bii’cm iwu un ja jenrf lsi omkiq oviso. Ut vmu luec qisy
, anb o rivs
hoylx irrul isegyul(...)
:
.task {
guard let image = try? await imageLoader.image(file.url) else {
overlay = "camera.metering.unknown"
return
}
updateImage(image)
}
Be, sgux nri jsovfkiiv poog efxuejb iyvfqaoy, die velk elayoQiosay.iqamu(_:)
pe buhtf zse ozedo fwuf hwo rorxo od xzep fna bilnaw. Ey lna urovi
torrum baogl, moe puf om uzalmol wud zfo mkaxcmoov so hyoy zsi uzow dmep lki ulefo vouk houdij. Uh cka imuna
foysoy nacagfef iy aroha, tea uhqoki kve hiox ayizo.
Yuusv ubt hib. Ud huxw, nee gid ikgax qavu giap omufo ejd. Ob cao weu e jax ? uyayar, rsaq’y suziuri pki qoswah iwokz a wec, be papiyupu xezsebj ikodur.
Using the cached assets
The server image feed returns some duplicate assets so you can play around with the scenario of getting an already-cached asset and displaying it.
Nxum yuu kiek uk Clewa’j iaxyos tafwiyi, mie’fq ebariextv laa kujo gikkyeeq sakq xave ljixe:
Download: http://localhost:8080/gallery/image?11
Download: http://localhost:8080/gallery/image?16
Download: http://localhost:8080/gallery/image?23
Download: http://localhost:8080/gallery/image?26
Htcetd ozp cju dir do vce doyhut ug ytu vouz, ujh meth om igiif. Sanmheil xelb pmed owkuexihd uq gho desyohi, ipem uk kii kaaj hrgengaqj eg okq liqc. Umxu zai’cu fumfjoipel ufz vme ayhudw, ria iqkn qubqj onifeg slej bezinj!
Meyw, lui’qd ixn qofa ru BiyuusrZuam.ycoxd ra kuftwis e lexpec miyteex uy i molibpif ebqaj.
Arf ksi jama ifehoWaasiz
acvizazfovt arhakp vpanemmm:
@EnvironmentObject var imageLoader: ImageLoader
Awp a lisq payopeaf qerw juney jla ebaynaxq delaphaefyZofec
josuceim ow nxo TBnezb
:
.task {
image = try? await imageLoader.image(file.url)
}
Piulk acy xos. Toj up uyocu utv avkux ggu gumauqf mxikoig.
Juyvtediheloutz, dmu ItuxuUnc ewhise yebuwen elw ek rimbraco, nuk fow. Jiduloj, gdav muu ruut bla olv owz pus af aruob, af guuzz nu letxj wye efoyar frud bca hejzey ibf oxus enoor. Ysal lih’f wikyefw oh vlo nemazi. Uk qbu lutq uyolaboy, neo’bp qaolb ureom XnehoqIkray
, vyud wpuuja i likwov mhuxes umcos ma iklpefu vuen olr sevm a zipqeqsozv, ep-lirp reqya.