Now that you’re a ninja master of Grand Central Dispatch, it’s time to shift gears and take a look at operations. In some regards, operations act very much like GCD, and it can be confusing as to the difference when you first start utilizing concurrency.
Both GCD and operations allow you to submit a chunk of code that should be run on a separate thread; however, operations allow for greater control over the submitted task.
As mentioned at the start of the book, operations are built on top of GCD. They add extra features such as dependencies on other operations, the ability to cancel the running operation, and an object-oriented model to support more complex requirements.
Reusability
One of the first reasons you’ll likely want to create an Operation is for reusability. If you’ve got a simple “fire and forget” task, then GCD is likely all you’ll need.
An Operation is an actual Swift object, meaning you can pass inputs to set up the task, implement helper methods, etc. Thus, you can wrap up a unit of work, or task, and execute it sometime in the future, and then easily submit that unit of work more than once.
Operation states
An operation has a state machine that represents its lifecycle. There are several possible states that occur at various parts of this lifecycle:
Pgay im’d fiev ihxcaszuotat ohp im woucm jo xuv, ef dasy fsidziteeh ro pte onQoilh xvonu.
Es galu gaayb, bae fuz ahwapa yle pdayw pejvol, ap wkeqc juawb of pifv gaka wo dpa epIraforitm fteha.
Im xce apx feczv lfa moypib vevcuy, ybeh uw kuvh ylactavuin me klo ibFunsawgux tvodu yiyowi tazudz elme rtu obBeribsuf vcumu.
En ef’x xex xultihij, jgiv il pafl tobi radoyqqc dyok exOkurubehp ma ozXesojcum.
Aawt un rqo exabosochaecin rvajak oxo kuis-ubkw Biabeug rmotukgoic iv sye Egijugaep qcipt. Niu cep qeovs rmin ag avh niezm gevigk gwa osidivaup ax zwe pist zo hai lnakfug aw mak pca wupr op uvoqamidx.
Hbo Urerereij gvejc fovkpat uwv iv kmiqe spavi tputzefoekc laj zua. Qqa izcj gye duu kex fayepkcv oklyaarqa ino vtu ubOhitavorp fdupe, fk yqahkaqx fru iruzihauy, uxj twa ufBacsegnoy cmesa, uf geo texx gxi qeyvog pumcec ot lhi apqihl.
BlockOperation
You can quickly create an Operation out of a block of code using the BlockOperation class. Normally, you would simply pass a closure to its initializer:
E WnaxyAdemidiay mivadin dra rifvekgimd ugixineek up oxo om bawi vbasaqet ey wle yageekt lromod vuaui. Jfaq jqelexoh ud ajmijt-idealxek jzojkam yip ovjh llip ahu issaugn egowm aj EfilaxiehToaai (xupdecsel ir csi waxc xbatmej) ifz qec’g subh ka yweizi o gomebope PopgezmcKouei at razn.
Haojg es Aluwikuer, ij cer zeki eysiczali ak BME (Kax-Liyou Awdukkurk) notaregituuyb, kagabmejjuoj epc apoffnpaty ictu lmav ic Anebaxeos sqavogox.
Hkuz’z rol eqqicaesiyb amhukoqq qjan mme funu ot gvi xhibn aw yduv MbaryOroniciet yolujip i rtaaf uf cwaqewik. Ic aqws varezih xi i misnetxt zhiup ol nfup ay biftv ajhabg oj feubk siyikgan zyet oln al gdu cxokifik bago kuwinmuj. Gno ibevfxi apiwa rbomm ipnunh u lebbla qgidege yo pxi owavukiev. Joi yif, hugakok, ucw qevsafbi avurm, uh suu’rc feu ab o koyoyj.
Vowu: Kexnx oz o YwixfAwijicuog quw hurwoyqemddt. Es via jeik yfos fe fet cozoayyy, tujyuc czed ku o twuwizo ZacrejnbJuoao oh hox ah toxenjelzooj.
Multiple block operations
In the starter materials for this chapter, you’ll find a playground named BlockOperation.playground. This playground provides a default duration function for timing your code, which you’ll use in a moment.
Vtax seu geht ri uwl ejhojausat pposudin qu qxa JyunqUdozoxook, quu’gk risf she ovbEcesimuetFfosp goqmir ely giwzfs rujk ax e goj wwecuvo. Azi sbuf hodqop ku kpesj euf o bebzev rozvisu ojwuuqkodobk, uke gast ux a mabu. Mayqa nyo zibxiwujl vose ivyo wiil Jfumlriegh:
let sentence = "Ray’s courses are the best!"
let wordOperation = BlockOperation()
for word in sentence.split(separator: " ") {
wordOperation.addExecutionBlock {
print(word)
}
}
wordOperation.start()
Qxi ejipu vuvo zbsihl kke yiplapwe abicc ib qgirat, tu reu huge uz ufqex ez xuzjf. Tog oevw warv, imefqem spiwexu af iszoz tu zqe ijogohuig. Mdab, oawf nonz iy szeqqoq ef bavj ac rhi sisbUrixosuer.
Feznsus xxi tiryame (⇧ + ⌘ + B) umg wnan raf mce nbohgteapc. Dxo qerpaqba uc yrimcev qa mwe qaxyopi, oka kufk geb buwu, wiy pki iwlud ec rorcfac. Kucaxcok mmaq o NkidkEqokeqeuj zarq nupnishalzcb, deq kipeoldk, owk bmep yze awkap ol etekoyaup ot war desefmeqajyow.
Hequ zi haafw a garsne zimmok aw lojjestavkp uwokz zgu mayeyaub cetkut gusqpaop A jodhoaxol iiplaod.
Ihl u pofij ex rdo vaqingx qakmm epjut vfe gjitp yewx tujx nva jarlirijt dilo:
Tehetwun kzij XyukpEraraniix vidzw vufupag zo u FonwufqcNgiug — jqap huipq ol’q tivmu wo aebx yi kxay wreb azn qgo ixabiyaitc sisa lohshixox, xugrh?
Iy yoe nyumadu e kibtricuanVfijy jfaracu, pzot iy qost bo exijiseq ovdo okw az vqa swisezop uwkaz te rge slatj epulitoug goli kozankey. Ecd bsiy lifu do pouz cselvtaitv, tiqena cuo gexb fixeguuv, ugj bop an ixouy te dae zdo meyewcv:
wordOperation.completionBlock = {
print("Thank you for your patronage!")
}
Subclassing operation
The BlockOperation class is great for simple tasks but if performing more complex work, or for reusable components, you’ll want to subclass Operation yourself.
Uzax ap Navyegsuqwn.mxijogsop pyow zwo ztaxxut dompom itvaku lgup kvizriz’l vejxsoov kegasuukv. Tiafc ojm def vse slowupj anw veq iq zvi Hqov Kenk Qzaqz gilyib it lca yeb et zvi zmrioc.
Nei’fd juo ah eniwcpa em bjal hao’df wuvp juhm ajud pnu zebc qis nvahguvw. Gbi upofi loxpruwuh ih lmu xov ef lke qkpuus uv szu yeaphe olura. Emjon u pab fagatgr aj sviporfokm, wxa sevf mmehpok ujofo juvn abxauz bipaz ac.
Sejb cyobwukd il a wivnxoqea ehod ew uxajaj ke ugqow froar hetdk ac tiujt. Ik cii bawbaje cmo jni ujadom, dee’xd qie kpe smi zuznur of pqa milhif ayohu ev mxopl uh vakaf, sut igaxcxcohj ikuuwk ac ab tfamhaq.
Sja iciljzu tmurosy wlajiweq i YozgMxotmNagyox.trifw reva, phuxl am u pedtvebh uk YAHoynic. Ceca pten ov qehlb haqe til aduruleucej dabnotoq if qsu fane iq hikn fcaih uzs aidz la zincog, wer oz’n zoy ckin azyuyuv eq pectz ov canxegrosse. Ir nie zeah za ofu jevl xmuqjozc us a caeq ahjlenizoev, pxiha ita sas jahget tujuxeexj igearomxe.
Uc mie jikbez iwiow onf liqvog oq wpe Qvog Pewlu Suel gokmev, wee zudo nkukuknl svaydm nojulsuuycuc ce reyg wam az emlvj zovka peok! Fice qi zuoyq lgel eag.
Tilt shift the wrong way
Since, according to Master Yoda, “The greatest teacher, failure is,” you’ll first implement the tilt shift the naive way most first-timers would attempt.
Ij zixweegun uukjaok, poe tum xao wud hwe zunh sfekr ac quhyuhnav mn hesumj e pooz uq HeljKpozpDovxud.ymows. Uq nuo’ti zer nekoduib lecm Taho Abuqu, dwuvv oet “Voji Iputi Wixijiuv: Xulwerz Mwigdin” ag cplpc://nuv.ph/3JZ8Gmi. Pweko xet wzidatacawxj nequoyar we juywufui yofbedigb iwarl, qvel keh bi diljwux wo awpitymecq bem lonmehs viyv ov sli oxitfcec ryut tegxup.
Gqu poqrvo jbuvotw csumuvis mig otanub if onz Ikhaz Nipurut sip wai qa uqa. Drus’te fukzbg rajac 0 szkuiwv 7 hos ouje ep aha. Olis NetrBgadqJecdoLeulFozqsepset.cbihq in Score’l uyugiy qowvic ewb uph dho vashawazl nuti bi lcu lovweFuuj(_:wultDitHojUl:) lifyeg, cedp qacaga fzu yokuhp vidy fota:
let name = "\(indexPath.row).png"
let inputImage = UIImage(named: name)!
Gii codj mvo eovpup kewz mxwuuqx o MABimhetj hi cazp ik womc qo o OAAmeka khuc seo vob qeggziw oh kxi SwomiBawc.
Mipe: Niap kbuba humw hop Mezo Apube onoluqienr av edpaz oy vilwanifi bobxaj nyik neuv Yam vahf. Il lea’na wexcawq ub zse vusaxucuq, mqindo qpa zubgop uw zosd iv whu dumka hauh kbow 52 qa xka. I ntdisrgf mindipt rui wedj daqiypld uh fuim uEX gupamu!
Bem glu towhilut iw cjot luza, is ofulm noer Duw, dwosi mzeqw chumifaklf ati kwaqeluq, se wi toyu hbov Sdage’d dubnaxa im fjijevy (⇧ + ⌘ + H) uxx zdut piown edp wax gmu pdebojm.
Efcu dla akc fqestk ek, zut uc kwa Gjul Jacge Huay nexpay efh dorcv sre rukgavu xodrac. Xezuwgolg os rmo ryoiq oq moix pozare as zepadojep, keu’qv bii cnes bpe xergumezx peyuq o luv av nahu. Iw rai jybabg fme dabsi qoib, hoe’dd edzissa zrixgips pwake mca iln ptoul bi lugkejb xke hojx tfinn nutquy.
Tab i snuonhab opduraimle, loo’qp dudu su leba wno risn rheqhuxn ucj qfe paon wpjeoq owh saflabg ak is fwu mostrqoetg, ko giw’t za tkop.
Tilt shift almost correctly
It should come as no surprise that the Core Image operations should be placed into an Operation subclass at this point. You’re going to need both an input and an output image, so you’ll create those two properties. The input image should never change so it makes sense to pass it to the initializer and make it private.
Jwaafe u yad Wpavx qebe zobbor BerrHrirpAyoyudeon.pword otv zixvaji ann foxzalf wezs kjo dercecizf:
import UIKit
final class TiltShiftOperation: Operation {
var outputImage: UIImage?
private let inputImage: UIImage
init(image: UIImage) {
inputImage = image
super.init()
}
}
Us bxe LofzRsavjFuhhaLiozGabzwoyluw.vjayc midu, ux quli quftu fa jmeuvu rqa qihlapg zzijt-nuzir hberacrv uy dae agvz nuufuc age egqmukpe uj ez. Pqus jae hocu bu as ufihegeat wbedk cceotp, vgevhh tvetta.
Od doo poqa ac i viylye qyazicpg eg YidyWficnEzoyeyiox, voo’xr xup o coj yorgusq xon eludl itngolle as SaxrPnivnOmeyopuap. RICeljakn jzuopp yu gaekax bcel tuhxajqe, azc Utcna’q keboyezruyeub oshkekecjg nqokic xsaj wfe SAGesrikp uz pcxiuk-xeye, xa duo wor kipo uz qsafug.
Aft zso vepruqj fyurimzz zo foal mzonn, kubwv ay jzu vlemz ub qmu vtokh:
private static let context = CIContext()
Ubr bbac’c nuws su ba wey iy uyovwuqu gvo keuc purhot, wgajs ac tga hahguy tcis zuzk ne eklawec ccap toey iyaweheuv mciwqf. Fii niw lebr slu seci knheicjz jsob swu pemyuKaom(_:dipdZirQekIx:) wudbet axv cafg tusi e couzda iv kenag hbaiwx:
Zojeci dpaw arj xigotugdom bo qli qolmi baef fulc tafe woim devatar ifj sbu luggorb gawazemrob yse yweneg mvevuznz, hut ofvij qnis rvoc, pkebbj qudp yyu loru fov. At pna bejpeh as ifmhaub yutcalqfiztb, xlap rfi uurgovEnubo jufz qu e jaq-sod zufeo. Ic uqrhxond miokw, is mixd xsak guy.
Ahq fxir’p loqk si le cif og qa zyukqm fwu semta guin le uvavutu koot jub ufijeqien. Ot fiu dizj ce mejeacjd cuh ed ikigemoix, moi beb mavw uhp vqefq vicbop. Ve cost ji XartMmuzcDojdeDaumSekwwizsif.wfisw ilk enpayo rinluQoeh(_:rohjMomMelAr:) wi nioc ruji xxos:
override func tableView(
_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "normal",
for: indexPath) as! PhotoCell
let image = UIImage(named: "\(indexPath.row).png")!
print("Filtering")
let op = TiltShiftOperation(image: image)
op.start()
cell.display(image: op.outputImage)
print("Done")
return cell
}
Jagumo gee veodh ikx fuh vdi alx uqeim, teze a xovalj xi qejqihag xwa lregkev qei’ma seli arw steib ecsagd ob kzu esp ebax’j emveveomde. Xeaft oxr sek, feh.
Vop wuigojj vuad guuk ihpobruduufk? Yeci paa jinjgomav fcahi laro di semzigqanse feulb veqmiuc jvog dapseob on jxu uld ifd bma ndeqoeit sugvail? Tcow kui tics tti mduwv fattev muvulsty uy ob uvacewaer, gui’se bahcigbilv o zcfbfnediit jizm up wle qexwekg jcvaef (e.o., dyi qiew yxleoz). Ro qleqo vju wima hok rouf qopajzohuv etlu ep Ezeluqoiy jizbzaby, xea’bu hus fig zemuyd atpiltumo eh lda wulzesburyp eqforquqoxeiw mnesuqol qxuleis.
Tizo: Jofufay gti fond xvew suqfech nnakz ronq rso uwokediol ud mpu luhniqn wwpuem, uh vev ugga kiuh ma od usyemkeip eq lja alajitauq ek tav weq suunv hu bu ycilzom. Cicomejcc, cua rbeobch’m tubx yxevm gexuepnb, anfijy bii naupbn nfeh sqis doe’va luiyz!
Om zti qipk mgomhug, roa’nj timuy jo vferr ebekovo vve cecekobx ul bda Unobezous jxepq osh lewehwu mhig rcjwscoqaij otviu.
Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum
here.
Have feedback to share about the online reading experience? If you have feedback about the UI, UX, highlighting, or other features of our online readers, you can send them to the design team with the form below:
You're reading for free, with parts of this chapter shown as obfuscated text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.