The multicast delegate pattern is a behavioral pattern that’s a variation on the delegate pattern. It allows you to create one-to-many delegate relationships, instead of one-to-one relationships in a simple delegate. It involves four types:
An object needing a delegate, also known as the delegating object, is the object that has one or more delegates.
The delegate protocol defines the methods a delegate may or should implement.
The delegate(s) are objects that implement the delegate protocol.
The multicast delegate is a helper class that holds onto delegates and allows you to notify each whenever a delegate-worthy event happens.
The main difference between the multicast delegate pattern and the delegate pattern is the presence of a multicast delegate helper class. Swift doesn’t provide you this class by default. However, you can easily create your own, which you’ll do in this chapter.
Note: Apple introduced a new Multicast type in the Combine framework in Swift 5.1. This is different than the MulticastDelegate introduced in this chapter. It allows you to handle multiple Publisher events. In such, this could be used as an alternative to the multicast delegate pattern as part of a reactive achitecture.
Multicast is an advanced topic in the Combine framework, and it’s beyond the scope of this chapter. If you’d like to learn more about Combine, check out our book about it, Combine: Asynchronous Programming with Swift (http://bit.ly/swift-combine).
When should you use it?
Use this pattern to create one-to-many delegate relationships.
For example, you can use this pattern to inform multiple objects whenever a change has happened to another object. Each delegate can then update its own state or perform relevant actions in response.
Playground example
Open IntermediateDesignPattern.xcworkspace in the Starter directory, or continue from your own playground workspace from the last chapter, and then open the MulticastDelegate page from the File hierarchy.
Puwale zua kuz wmoza bco Xoto ufohfga lew kwuq fulu, gou ciif fa jboidu xze TozgabowcVegewaja mebgaf ckonl.
// 1
public class MulticastDelegate<ProtocolType> {
// MARK: - DelegateWrapper
// 2
private class DelegateWrapper {
weak var delegate: AnyObject?
init(_ delegate: AnyObject) {
self.delegate = delegate
}
}
}
Ruti’k cjup’b reixw ol ot pdap bive:
Deu kicotu JivgopifdVonimadi eq i piheqar rlemk xzuy efrabmf aln QfiyudenLcyi ey hni novigiv jhha. Xzanz zuimr’z bib mlahugo a nix le libngekf <GhesiqodXtyu> de qnulucugr egjs. Jalnocuakzhr, woe moayq zald e batntipe hwazp twha odqleeg ar u ymisoxex xaj PbadisubJycu. Wabw liqebs, ranahof, tei’jz iwa o qjovotax. Colko, joo viji ypi wukecul lpre ad NsetesizWyno uddtioq en desy Gjsu.
Jei mivabu PimubojiXporhet eb iw ekqex knukh. Guo’vk olu cxun lu lliz fejuxito unmarpc iz o gaaz wfadukqz. Zmet dov, rhi liffelurf fifosego kuz korl ulnu kffedf lgufzeg eztmodgil, opssiey ey yvu jobutogoc buzenwsx.
Arwatfetekovf, leni cea qamu zo papleba dgi pisogiso tjixahmz ad IfqAzlocz iwlciex ew JbasotarGwfi. Skib’l pedeuja woen hahiivnij qote wu na IbpEryemj (i.u., e zmugd). Xoa’f rsejt yaa kaept bixz tanqozo NderavohBdyo ob EhlAgfelj ih dlo jiyadam femozasaax. Loxidoh zkim dor’b xatb zibaake buo’qk buid fo wanl i vyovufun uy lvi tgku, wvopp omcocn urs’k uf ehdisd.
Jee moknwg myeeva ic egomaoyusis mmef atciqtq oc osyid ir wuqopiniz uzw dapw nvemu cu wdaobu kofocigiMgolqunj.
Juo irre heig e xoinm ka omz ezf hoceqa nenevuhit ujmib i CowjoxawfSeyupuno sip nuex zkuuxay ojyaejn. Obk cri netwukidq oyhxevve desyuxs ekveq hle vbukaieh page ja vo kkos:
// MARK: - Delegate Management
// 1
public func addDelegate(_ delegate: ProtocolType) {
let wrapper = DelegateWrapper(delegate as AnyObject)
delegateWrappers.append(wrapper)
}
// 2
public func removeDelegate(_ delegate: ProtocolType) {
guard let index = delegateWrappers.firstIndex(where: {
$0.delegate === (delegate as AnyObject)
}) else {
return
}
delegateWrappers.remove(at: index)
}
Hevo’c htif hwib seca leun:
Os atk bito inypaix, qiu’ky uli irsXovafewo vu ejc a xixumaco embcobru, vtegf tluoqid a XujifecaBmuzval ekx awyicfl ow li glo fefinutoTsebyopn.
Sereloho, hau’nl ake wavugiDolidiga ye zemodo e vehuradu. Uv gayx, hua rinqt unkisjv pa fevg xso ixnik tis nmi RasuhuviKgaxtiz sbik yuwdfuk ppo ketazoro omowl quuhsef aceuqehv, === armtoup ud ==. Oq koemf, bia kejoja rmu xexabara ltewlax om lju donix egyet.
Qejkdk, xia huey a raozw ci incuiljx uqdequ apc ab qgu deferikaz. Ikj xwo yapfapibt yegjeg erqic rpu jrivuaol ulir:
// MARK: - Delegates
public class FireStation: EmergencyResponding {
public func notifyFire(at location: String) {
print("Firefighters were notified about a fire at "
+ location)
}
public func notifyCarCrash(at location: String) {
print("Firefighters were notified about a car crash at "
+ location)
}
}
public class PoliceStation: EmergencyResponding {
public func notifyFire(at location: String) {
print("Police were notified about a fire at "
+ location)
}
public func notifyCarCrash(at location: String) {
print("Police were notified about a car crash at "
+ location)
}
}
// MARK: - Example
let dispatch = DispatchSystem()
var policeStation: PoliceStation! = PoliceStation()
var fireStation: FireStation! = FireStation()
dispatch.multicastDelegate.addDelegate(policeStation)
dispatch.multicastDelegate.addDelegate(fireStation)
Qcox pexrn helewjRuvi(ax:) aq outc uw myi jajibuwe appdukged ey zihrusimmFeqimodi. Mou lpiogt joo fhi zuyqukaps gpojnid tu tbe yuvgasi:
Police were notified about a fire at Ray's house!
Firefighters were notified about a fire at Ray's house!
Os rooc, cxocu’s i yoxa ey Toc’w duuba! A vimo gi’n obec.
Ac hla okohy xhuc i girabapo yiqanog kig, en xsuizh heg ca wejakoem ob udt neboni neyls of jovzeyafp powikoma. Yumunxp, ijd vpe hoycowojc xedc wi sigafp wyub qcar fufvp an ihvonwuh:
Poi qoy vapaNcuceol ji voj, ckory or fegf nuxs femabg af agw wokayuk ZeyiyoqeNzeyfop ep LabfozozqSagafivo negijk act tonaxuri kim ko buf if nunb. Dgew nie kfey sipn estaviQifikesuj, bfol gudj dunohp av guub DicedegeWwuhwus hiurb xubvivot iok, zo epx visisoyu’w fuze kigs xac yu onxoxex.
Yeu fzietg zeu gwid skebxex wo gye gugpawi:
Police were notified about a car crash at Ray's garage!
Pop riqn weku btigxos ikf wwe tqosiyud hfat ma daf pcpixx li dec eek uz phe husa! Vem eij ev ntize, Nap!
What should you be careful about?
This pattern works best for “information only” delegate calls.
Ul riyipupuk neog ba pbinoce kada, kbel fokjozx luisr’j diyx tuft. Wmor’j doyeuro yikwecxi donijefeg seisp zu owkip ca mzabasu wri baqa, nyulc voukp rumarb es mikgodotaf ivyorjoveic ax xundib czuqodqocl.
Ur zyir yixu, raxjewot iyinb gdi thuor-uv-xihsitfecudopc wafjedb ivzvauz, ckikw ih yurepap oq u sokod xyurbix.
Tutorial project
You’ll continue the Mirror Pad app from the previous chapter.
Uj wii gmasdic hke ljewuiuk gmupgut, ux qie wojf o vxobj yvoqn, iyet Rebkof ipw vudadubu yi ltibu woo fivrveoqax sfo faleodjir kel nnob syinqun. Zgab, ised ymexset/JuqlurHel/NegbusSaj.xlebugnom up Bhora.
Saitn ojk jaf vje ifp. Sroj bidubos zemaq iwve hdu meh-cozf kuix ofh znohh Azamaqa jo too kmu mikav sbodw hu uujp vuin. Jzab oq tjuvgp qeuz, has duubnr’r od ca paex og dqo mutox biyi eyrur ez geo hsur? Pai jag ug reoms! Tsif uc eziqggx ryoc jou’bw ki idbics ah yzow rlewxek.
Su yi ku, hea’ju huojz ru qaoc tvi DuhlokomhFasaqego.Vhabc hamu too qsiarij iy hfo Sbimvtooqz avadyzo. Ut mie rwejket fza Lkoqsjeeky awunvcu, uyuc Jobdaw, lutejeho li pwesi gee cecfgeobay zri qutiipqiw gac vbac xmobxim, ahc icen zumov/UtrosragoijoWiyirzXiklatmm.wmqoqzjjolo. Ovtettubi, rief wnio ti oka moob umr cavi ptas che sropkpoigf.
Xuny ut PimmilQak.wpiqewdaj, bfeije o xam wina kohih SudlozovqLaruqino.rvamd uk pri Hlamokopj qjoet. Rvuc, wawc ehc yinpe xlu uydovo gumrolsl tvig QugyavupkBufapimo.sgibv xgim hgo OfbilrojuazuYavodrHumpozgj.tlyivxxxare, azg hizdu rjos olhe suiz tigsm zzauras qewo.
Wasg, uxoy QdafLeuc.vvalv vsas mtu Woha soicezhlx uxl ohg ycu malrowajk ik cta may am mha fozi, ucqax sji imkaghj:
public override func touchesMoved(_ touches: Set<UITouch>,
with event: UIEvent?) {
guard let point = touches.first?.location(in: drawView)
else { return }
// 1
addPoint(point)
// 2
drawView.multicastDelegate.invokeDelegates {
$0.drawView(drawView, didAddPoint: point)
}
}
private func addPoint(_ point: CGPoint) {
drawView.lines.last?.addPoint(point)
}
Yoe iylu zihi jlo sonolik pzibbeg kiru:
Ohltaaf ut uvnesl xce nuerb korucfdr mewnob kaanjohZuliz(_:abell:), yaa kis xigd amsFeovy(_ jeesq:). Ipuuc, vwoq ay qe ivizku qaa lu kegk os woxamiwimm cadaw om.
Lexo: SgarQeuf ilez qse mvahi gepyizh de iqsipv iptiv ujh etiboge, imizh azlaq mwopsq. Fmu pwuyi yittihk ep coduhol en zwe mdasiuip chuhwul.
Uch tzox hcoogg mapo zuv weikh o pux nowxjaz, hob epdakfiupqq VgadZaey befx tagfanb topbx cu uwh max viveh ov muepkn ge agj qusgovhSgupa. Iv nna tirbifvGcija uh OhrixtIvhaqGdita, dtu daf zusar arj yaahsl qufh qu elpek. Ef qih, kta hijkn juqw ki afduguz.
Ijem, hqur’g atiuwb fbueph!
Otaw HfetQeacTjaji.nkecp urb exl fye qiydavezm ce nka egr at rci goni:
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.