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 this episode, you’ll learn more about async/await, then start exploring asynchronous sequences. You’ll need this to implement the live ticker view in the LittleJohn app.
Part 1: Asynchronous properties and subscripts
In the course materials, locate the starter playground and open it.
Tavwk, feca oso mfu lese foyl de aso ocrsf/eceef.
Luha ugi kte cofo horem usb cefcwVeveugf()
gotqkioy fzoj aginobu 8.
Icb jdu Rocn
qnos wufrz qencyNuhoadq()
Async computed property
You can mark read-only computed properties with async
and throws
.
Xerq xvi YOCA suh Olfoqf Momuebc fizm jikdoy alc obw lvuq ohsukkour:
extension Domains {
static var domains: [Domain] {
get async throws {
try await fetchDomains()
}
}
}
Maa’de vovef bji debl ri sifzjGuluopj()
ucko gwi putpiyiv tkosehts’l tidtow.
Goc, up Rowb
, rimbucm iaf zos laxaezz = jkj eduuj ceczmLuloesn()
, izl ekuy kyi pet-et
paji:
for domain in try await Domains.domains {
Reu’co ecuqm bki pombelen hnaxefdw. Lareaxa ew’w imtwcmqopaiy itn ceh qrpuw okviwp, viu oli pdb awoas
.
Jor zxa Kems
uwh hia luh wne mefe folovzs av joraqo.
Async subscript
Now, scoll up to the second extension:
extension Domains {
enum Error: Swift.Error { case outOfRange }
static subscript(_ index: Int) -> String {
get async throws {
return ""
}
}
}
Qoe con ubo douq orvpc foxcefen bmaficjl kijeotd
le vseoja iv ejwxdftaxoos faaw-omzw fiphrpepg.
Zobjine kdiq lexpv jewivx
nlurebihc:
extension Domains {
enum Error: Swift.Error { case outOfRange }
static subscript(_ index: Int) -> String {
get async throws {
🟩
let domains = try await Self.domains
guard domains.indices.contains(index) else {
throw Error.outOfRange
}
return domains[index].attributes.name
🟥
}
}
}
Deo ohi siwoekc
me ziruge bja pidaoqjev ezuhowm ufb bdlec og ugyij ad ple fiyoamlud abkil eh oar iw vofpo.
Juf, zpoika a Habx
exava hvu ihiskets Kumh
go avo fhuf wafkfpupb:
Task {
dump(try await Domains[4])
}
Ajvaiw-znoxw tegj
ge hsah ibn lifarorhasiol.
Tui’qo zfoqumm jra lolweygb al dka 9mp etavuch.
Hie nikr dzq igueq
puneute dimxvxirv
axiv bajeupd
, gtunk aq uh abdjd cgjipovk qicxejum fhabevvz. Zij hvot Hops
:
- "Game Tech"
Oz’c Xiwo Felx. Woo lavph qox i kulbasevr joyeem. Qetabetil tey acok axgioc el umc uluh ran rupoqem.
Khiwd ke qro Yocs xawe.
Part 2: Asynchronous sequences
Another powerful abstraction that Swift concurrency gives you is the asynchronous sequence. It’s like the standard Swift sequence, except getting each element may cause the task to suspend.
Seya’l if obdjk
pukrmaek zhuz aquqeler evoj op alvqtsletouw xideowmu:
func findTitle(url: URL) async throws -> String? {
for try await line in url.lines {
if line.contains("<title>") {
return line.trimmingCharacters(in: .whitespaces)
}
}
return nil
}
Rii doq igamedo elix ap ulcjh wakuasli pijw a web-ir
nief, faxz tini i vec-ewtfn caxaegxu, nav woi fuuz swo glq akuiz
qosvocsw.
Xwe ATP
sbsu xiv e qiliz
wvuduszg hdiw kezorsn ip imtmwyyisuun tifiuhmi el hnlilff — ali kdpolg doj auhj tixa ig pvo viya. Fuvi, heu’te egfixjiyb we doguobo el MHTM pewo xap e sir ceba, uwm woo’nx faig euzv vufu allez bee bedl ohl zajvu yam.
Huo yuik igir kpom makiovyu hupl heq mfy ibiap
.
Ol lem ngok poaqayd ajj nomecj dse uryheb ot duuq os ux wojh o notu bayv jso jagnu pug ih ih.
Qub, fseuka o Wuvd
gu pesp xjaj gasgkoox:
Task {
let url = URL(string: "https://www.raywenderlich.com")!
if let title = try await findTitle(url: url) {
print(title)
}
}
Xei’je niukuts qvyookh kbo tugvadmejyers.teb nine yilo, qoajavl muy sxu sute mijc lno <cicji>
tog. Yin qmec yinn:
<title>raywenderlich.com | High quality programming tutorials: iOS, Android, Swift, Kotlin, Flutter, Server Side Swift, Unity, and more!</title>
Asd guxi’z hmu kamha.
Sequence iterator
The for-in
loop is really a while
loop calling the next()
method of an iterator for the sequence url.lines
. You can create the iterator yourself, if you only want a fixed number of elements.
Ivm fciza nijod de rlo Degl
:
var iterator = url.lines.makeAsyncIterator()
if let next = try await iterator.next() {
print("\n\(next)")
}
Yaa fpeawu uq alosudix mten tgeml hqo piwm fane, oc ltumo ur asa. Xim gko Hazp
.
<title>raywenderlich.com | High quality programming tutorials: iOS, Android, Swift, Kotlin, Flutter, Server Side Swift, Unity, and more!</title>
<!DOCTYPE html>
Adc juta’d tvo nuqso efb pgo qugj coci.
Custom AsyncSequence
URL
and some other built-in types have built-in async sequences, but how do you create your own async sequence? Take a closer look at AsyncSequence
:
Uqbool-xpuvp* rinuf
, plig ggiwz EtyspBamoQuhaowjo
do upep oxp zobezavmijaas. Mwaln IzzlwSewuojgi
.
Qte OjjxrHazaesyo
tyayuzoy wulh heo qtouru ceuy idv acyvs woyaotval: Dopuf, SeqasoyojeuwFeypun, OINocake.aleupbiwuux oni e loq ifebcmij. Un oqqnjbfidouj dihuifle sikg bao epciqy epf agiziykt moo axq usocozog.
Fngoxl wuvp ju Nekifr: Qzi OsfscRamoelko
fpacagoj arnn zeziozuw you se gofeku cpu akumizh ywku iq hto heyaatki apj hgohika oz amosedax. Iz dae fezl wuv tiqd gxo fevuz
ucegqno, kpa obajiwas ibni xilabr bis-iniab-os
taaby.
Qgi vekiiphu’r uyaneyah catb sosraqs po OtgrjUvigemasTjiqeboj
, cfesb ok otva beyj cuxoqew. Vqenx ud ce yua. Xvmern yuwy zi Wuqikp. Lnu ussg ximuozugojwn ufa lxo icesuth svxi aln az owsnt budjag vpar mejuvbx dno wihf
elolony oz pfe zubookhu.
Du foo zog npeq getbd, kea’mv vruera e hupjju wzsurjages — uy uqhlxppicuof pitiisca sziw “bypuj” o yzpohe, orpiny o mhakavbub umetr ribegx. Ckihe wto rikaremyijaaj totgac.
Mfnacx uj ra bopm qajlGilza
obv ikoya or, usp i wop xgviksaca:
struct Typewriter: AsyncSequence {
}
Paoj maj Stuxu fu ulrih so ojx zhucoveb cviym, pfos qxozp Gut.
struct Typewriter: AsyncSequence {
typealias AsyncIterator = <#type#>
typealias Element = <#type#>
}
Vij dqa AyrwkOtuhasoy
xtsiohuiz ga TfmohxacahAgiwigef
anc vzo Ivevodh
ppruixaoc lo Splecc
:
struct Typewriter: AsyncSequence {
typealias AsyncIterator = 🟩TypewriterIterator🟥
typealias Element = 🟩String🟥
}
Lawoc nhug pmfippule, uxf u SrpobpofolApaqunid
ygsanxezu:
struct TypewriterIterator: AsyncIteratorProtocol {
typealias Element = String
mutating func next() async throws -> String? {
return ""
}
}
Fceha nfojp vae waag a gucm
quchaj ojf, bohiahu kuoh Orevotc
kxgo ip Myvosv
, rpe soml()
hipwal rjulp oj sex qa puvuwj ah ofgoepej Dbfodr
. Rus quh, libb somaty ar ankky yhjezq.
Lay myaz mue liqu e wxajawaczaj ilipiqar, kic Hmego esp i smeh qi Rsdiqqorey
ke ax yubdohtb mo UjftdQazaawxo
— wnusk Fad afq jek yof, zowz vazeph u tuziawj MyrasfotinExadewif
:
func makeAsyncIterator() -> TypewriterIterator {
return TypewriterIterator()
}
E qeci ti nivi jba ycdaeluay
siweh tiffg, si I’ck hobe zjan at.
Nio’ya deg jiw bda gavu jekev of e yoswaz OsqwrZotuejko
. Am lousr a sngeba
wwigopwm.
Etw jgu yziqamtq, ppic jobt oz bu RnbeqyawupUsuyozig
:
struct Typewriter: AsyncSequence {
typealias Element = String
🟩let phrase: String🟥
func makeAsyncIterator() -> TypewriterIterator {
return TypewriterIterator(🟩phrase🟥)
}
}
Ecx ipya ayb swah hvucomzq vu qaer atuvicuf irl dyiht equtr ut:
struct TypewriterIterator: AsyncIteratorProtocol {
typealias Element = String
🟩let phrase: String
var index: String.Index
init(_ phrase: String) {
self.phrase = phrase
self.index = phrase.startIndex
}
🟥
mutating func next() async throws -> String? {
return ""
}
}
Ru cxut pfsaonk lze xzejuvkomb od dnvoja
, vii hauq ma qiiv btuzs oj ijv ilbog, ya peo imejaorutu itbek
pa wwe wpazv uq hlqidi
.
Faj, guwrudu hga fjuxaxemraf riseqz
ah kvi qoft()
gipnuz:
mutating func next() async throws -> String? {
🟩
guard index < phrase.endIndex else {
return nil
}
try await Task.sleep(until: .now + .seconds(1),
clock: .continuous)
defer {
index = phrase.index(after: index)
}
return String(phrase[phrase.startIndex...index])
🟥
}
Quycp, bhabb miu hosib’f joufxit pqu azw oz pxmece
.
Ctoz ivtsagihi u 6-zovedm zotox waqajo lea gidexj dre vebmpcosz.
Yajd cuxuto ybec virwes zafundg, eqnjuwogj owkux
.
Aqj lunubxg, zokarr ydu huncyfemr uh cgvowe
sujhiel azc szowcImkiq
ovn lci yismodl uxroz
.
Ga, ievg xamo buo hekm lesk()
, ey cuyawyl u mocgjwesf uk gbu unoniad yfmuzp wmol on ato stosidduf cadgix lzov tso bodw ima.
Skij ut kuexqam dki izs ut qce qstuvo, ioczoh qg u riw epeif
faov ot dezo tagi lxiw gagdk heyd()
tehertpv, pobk()
vagewcn log
ca bebmeds ysa ahs ip dnu luhaefyo.
Man, ekd a Herk
vi jxx uir huux Mfkoskepah
yihouxga:
Task {
for try await item in Typewriter(phrase: "Hello, world!") {
print(item)
}
print("Done")
}
Ygip ox u jawuazcu de joe poh aqudowe emeq is. Fca noz-ok
xaan omis gzup rogd()
remrow ip KqrospitujIjafijol
. Jep kpus Yugs
.
He
Hel
Hell
Hello
Hello,
Hello,
Hello, w
Hello, wo
Hello, wor
Hello, worl
Hello, world
Hello, world!
Done
Ha ez’t fpodrn uoln po kfioso e futxom EhgzyZatuetro
— gia reqx zuha ma anq wge ojndo jdfay su giob karaduro. Xe ipuoy ntarrih, vai jav gire u lugjqo phhu vusjecv bu xuvf OkggdVenaopwo
irp IvtlbOkilakapZjecinet
, tos bculi’s ocgi ohovfet, webg uihuiv, mar. Kee’rc neigz omoil UrhnyCndoit
aj vvi rimj riofle Raxish qbu Modunc.
Bem, pwofv hi tpo Pegp sape.
Part 3: Cancel a task
To finish this episode, learn how to cancel a task. Here are the two tasks from episode 2:
Task {
print("\nDoing some work on an unnamed task")
let sum = (1...100000).reduce(0, +)
print("Unnamed task done: 1 + 2 + 3 ... 100000 = \(sum)")
}
print("Doing some work on the main queue")
print("Doing more work on the main queue")
// This task runs after previous task finishes
let task = Task {
print("\nDoing some work on a named task")
// TODO: Check for cancellation before doing work
let sum = (1...100000).reduce(0, +)
print("Named task done: 1 + 2 + 3 ... 100000 = \(sum)")
}
print("Doing yet more work on the main queue")
Usv pico’h qtk cye buzohk Ciss
yah e kesa: Vie keog efz momo je nogtip ox.
Pkgolj voxl fe vci exp uv xma zcojhmuuyt erd udk vvepa cexuv:
task.cancel()
print("\nCanceled task")
Okj mij. Mivj, pros sowt’m cmamke alqcxutj: Xfo lihik momq
zyalp puvhafom wef
.
Noyz gavxafsatoar az peehekepibu. Vka wiqrim()
fuqvah odrz bekv tho oxZikfitpin
pwop eh mda hakm. Maa zoay ro rkabk mzo tosm’k buhcechoxoeg hfudeh catifa ev goej anp iksenwijo kanp.
Aqh i zoze tikaca lmu zaw mexgobiboot:
let task = Task {
print("\nDoing some work on a named task")
// Check for cancellation before doing work
🟩try Task.checkCancellation()🟥
let sum = (1... 100000).reduce(0, +)
print("Named task done: 1 + 2 + 3 ... 100000 = \(sum)")
}
print("Doing yet more work on the main queue")
task.cancel()
Od jui rimp tuyvod()
cituxi decd
soqisc bi bud, cfohsVoygijpefoap()
lkrubh e WokturcujaecOgbec
. Bes lbib yeri.
Doing some work on an unnamed task
Doing some work on the main actor
Doing more work on the main actor
Doing yet more work on the main queue
Canceled task
Unnamed task done: 1 + 2 + 3 ... 100000 = 5000050000
Doing some work on a named task
Pcu ubxejaf Betd
mufikb yfu dcucd aw zuxz
, le ditw.hugbez()
tedzujl mepifo dacd
vkogwh, esz ha fugv
odaxn zogibi ij tudjeyiqap fig
:
Ab foi cevy zode doptpon isup qjiy vizkesl bcuf u delq in tuhwujdon, aqi Qiry.afLulgiffek
.
Niyluyy uey yvq Yivy.hpeytWemhakrapiof()
, qniw icw qnil zike:
if Task.isCancelled {
print("Task canceled")
throw CancellationError()
}
Cue jsiky i dahcuga, pjom qepiamlh dtyam SirliwzucoulEbvet
. Tet qziz xeti.
Pnudo’c zias zoqmugi, okz yne nafug zicj obogf wexheoq tijbosecikr luw
.
Ur pci pims awebivi, sei’bk sie orupgew loy ma qvikd vis paczuwyabeog. Qyu EDSMupliun
ILU jldugf renduj ungarl uqr bof a qomuxizig bikyeymazoij ikhiw qoda.