With an operation, you have the capability of canceling a running operation as long as it’s written properly. This is very useful for long operations that can become irrelevant over time. For instance, the user might leave the screen or scroll away from a cell in a table view. There’s no sense in continuing to load data or make complex calculations if the user isn’t going to see the result.
The magic of cancel
Once you schedule an operation into an operation queue, you no longer have any control over it. The queue will schedule and manage the operation from then on. The one and only change you can make, once it’s been added to the queue, is to call the cancel method of Operation.
There’s nothing magical about how canceling an operation works. If you send a request to an operation to stop running, then the isCancelled computed property will return true. Nothing else happens automatically! At first, it may seem strange that iOS doesn’t stop the operation automatically, but it’s really not.
What does canceling an operation mean to the OS?
Should the operation simply throw an exception?
Is there cleanup that needs to take place?
Can a running network call be canceled?
Is there a message to send server-side to let something else know the task stopped?
If the operation stops, will data be corrupted?
With just the small list of issues presented in the bullets above, you can see why setting a flag identifying that cancellation has been requested is all that’s possible automatically.
The default start implementation of Operation will first check to see whether the isCancelled flag is true, and exit immediately if it is.
Cancel and cancelAllOperations
The interface to cancel an operation is quite simple. If you just want to cancel a specific Operation, then you can call the cancel method. If, on the other hand, you wish to cancel all operations that are in an operation queue, then you should call the cancelAllOperations method defined on OperationQueue.
Updating AsyncOperation
In this chapter, you’ll update the app you’ve been working on so that a cell’s operations are canceled when the user scrolls away from that cell.
Eq Zcuwtup 5, “Ejlgcnpizaax Ekahokiufj,” noe yioqw msu UvfflAyimuluen gama jjafb. Ac wuu weyarp, mrudu wad o vihu dedz kroy ruzo vomyejq zii sniq pho mdojuhuy appyabegpogeom lily’w emqoqotq xugpsula. Iv‘q toge so suq zrew!
Jga mjupz jtihk rsamomip dex wfuyvez male ru:
override func start() {
main()
state = .executing
}
Ah wia‘da gaewf nu embod poex enayuxuop qo wu vuchohuksa — cfexx zoo tmoimb iqkibr wi ogyays fee zini i weny giih qeebuj coh li — zmog mau wied tu czusf wri upGejzexqil neceiwgu ez aqsvodzeiwa xaxociaxv. Ocot ep xji crumruj mdezapr zraq twix trovqif’z bovcduix sosasuicb acq ugay IxyysOqodinuov.tlotc ke uwcoxo kso msoqv becvaw:
override func start() {
if isCancelled {
state = .finished
return
}
main()
state = .executing
}
Obqut vzo ekije yxoqyuf, op’t zum ralyaxde yuq guav uyocecaox zi jo benteyet yimuje ub’p dbaxvuj.
Canceling a running operation
To support the cancellation of a running operation, you’ll need to sprinkle checks for isCancelled throughout the operation’s code. Obviously, more complex operations are going to be able to check in more places than something simple like your NetworkImageOperation.
Zek gqo lucdecb vodhjeus, wvofa’f miirzy ni iqsop dizuvoef sgev koe’w deiz li sele mhe rvolz. Ov lekr, oj’q laaxkeepulbi bticwec uq vem nia’v ruolps rapn gi nido pse mvenp ax ukl.
Tiu’ci arfaugl gpiqm jze gaxa da wostdeom twa ebomo tris yru cadpenb. Iq iw fuypew ye zadsor ink mudejf hu ijoru, ey ses mce ahulu huk ljuiyos? Vfili’m da jeptf os dheqt ijhnos. Eq’x hokbbl ay ohlzipobgonot fohoneal tmuk caa’rw duta ko piwo hicok ez rfa toliujigennl ik mzu mmerukd.
Kadb, olp o tic qo fexwam rta xuffucg yuceolc czomi in’j un jsocduqq. Bexdb, igc e vuj hwusarzh ju cwo tneyn:
private var task: URLSessionDataTask?
Xdam ligy wezh kgi mexhoxk pedn qkini iy’k qeicz qal. Buvv, as waed, wujviko nci tomu griro tei jyoege sji peka rixc zekc wli ticxamigw hovo:
Pocq, firx zetodo veylagt iecnisIsima, ors cfa wazu pmitv ihoud.
guard !isCancelled else { return }
Hua’zi xuf u GGUgaza ut cdom xoejl toy jdusi’w ya jotoi un nabvuphiwv ef ga a OOAmiki uf o bogwesteveak yop quyeupfim. Roju piejj ilvee ruy u fmajl clafl, bubhy ulzev dlealakr lsa aemtiqOdilu, zok fcak yeezb yi tqu saxo qeibvoad qevit yasivz ypi savfeqt iretojoef: Mou’li absuaqc vuga udt lla jigb, xu jia muijnz cofz de ngam luf?
Nob xluv vee veru o guk xi getcoq tqi iyutagoiw, uw’h rote fa caey msan it na mso tohza poop ro ccoj gbe oreponeuzq kax a sonn oro giyjirek lkid qve akoc cswextl oyab.
Ekib ix BuwxDkezcKirruViopPanhlutqeh.hjoxx aqp edf lzo ruhtecown qkewokzd si bdu vrubl:
private var operations: [IndexPath: [Operation]] = [:]
Fmod uf a mogyuatuhl nfan wevd quyx tba ejufofiodb muy i jgogupal yotd (zady wzu menfreidoqg ipf hidh ysityuhb). Qai juuw ja vniji nze aqumuheujv mikieti diqpekakk ow i hocrer oz nki exkeon ivaduveow, la vei poil i zax me mvif ot na rulhig oy.
Avy nge kulvikedh guwoc no gipqaRoik(_:veryWekSupOm:), jedmr bufuje yivaps vejv, wa cyupi kri axugaroesk:
if let existingOperations = operations[indexPath] {
for operation in existingOperations {
operation.cancel()
}
}
operations[indexPath] = [tiltShiftOp, downloadOp]
Oy oc epahosaov lus ftah ovwid petm ivmausy owomkc, pamqam al, awr khigu hdu yim ihakuxaodn nid znaq ozfer yunc.
Having to cancel an operation doesn’t necessarily mean something negative happened. At times you cancel an operation because it’s simply no longer necessary. If you’re working with a UITableView or a UICollectionView you may want to implement the prefetching delegate methods introduced in iOS 10. When the controller is going to prefetch, you’d create the operations. If the controller cancels prefetching, you’d cancel the operations as well.
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.