Ciao a tutti cari amici di iProg, oggi voglio parlarvi del Pattern Delegation, Il concetto di delegazione offre un modo per realizzare un canale comunicativo fra più oggetti. In iOS questo pattern è ampiamente utilizzato e permette agli oggetti interessati di auto coordinarsi quando si stanno verificando modifiche in un’altra posizione all’interno del programma, tipicamente attraverso un’interazione con l’utente. La delegazione è una tecnica utilizzata in ogni applicazione iOS; infatti anche all’oggetto UIApplication è associato a un delegato, UIApplicationDelegate, che risulta estremamente importante perché ad esso è affidata la gestione degli eventi chiave, come ad esempio l’esecuzione dell’applicazione, la terminazione ecc. Una Sorgente Dati o Data Source è praticamente identica ad una delegato, eccetto per la relazione che intercorre con l’oggetto delegando; il delegato rappresenta un elemento di controllo dell’interfaccia utente, mentre le Sorgenti Dati sono elementi atti al controllo dei dati. Un esempio sull’utilizzo di quest’ultimo meccanismo di comunicazione è dato dalla richiesta di un UIViewController, in particolare di un UITableViewController di popolare o modificare determinate celle con specifici informazioni, provenienti dalla sezione di modellazione dei dati. Per rendere le cose più chiare vi mostrerò un piccolo esempio.
In quest’ esempio creeremo 2 Classi 1 Ferrari e un ‘altra Audi entrambe conformi al protocollo Corso
protocol Corsa {
func kmPercorsi ()->Int
}
class Ferrari :Corsa{
func kmPercorsi() -> Int {
var contatore :Int = 0
var km :Int = 0
while (km < 100){
contatore += 1
km += Int (arc4random_uniform(20))
}
return contatore
}
}
class Audi :Corsa{
func kmPercorsi() -> Int {
var contatore :Int = 0
var km :Int = 0
while (km < 100){
contatore += 1
km += Int (arc4random_uniform(10))
}
return contatore
}
}
Le due classi sono molto simili con l’unica differenza che la classe Ferrari può percorrere più KM in meno “tempo”, la variabile contatore è molto importante poiché è proprio grazie ad essa che ci sarà possibile determinare quale delle 2 auto vincerà la corsa.
A questo punto dobbiamo definire il Delegato e una classe che gestisce la gara
protocol DelegatoCorsa {
func corsaIniziata(cors:GestioneCorsa,f:Corsa,a:Corsa)
func corsaFinita(cors:GestioneCorsa,f:Corsa,a:Corsa)
}
class GestioneCorsa {
let f:Corsa
let a:Corsa
var delegate :DelegatoCorsa?
init(fer:Corsa, aud:Corsa){
self.f = fer
self.a = aud
}
func gara() {
println(“3\n2\n1\nVia”)
delegate?.corsaIniziata(self, f: self.f, a: self.a)
var ferrari = f.kmPercorsi()
var audi = a.kmPercorsi()
delegate?.corsaFinita(self, f: self.f, a: self.a)
if(ferrari > audi){
println(“La ferrari vince”)
}else{
println(“L’Audi vince”)
}
}
}
La parte pi interessante di questa classe è la funzione gara, per prima cosa viene chiamato il delegato per avvisare che la gara è iniziata, richiamiamo il metodo kmPercorsi per “simulare la gara” e infine il delegato ci informa che la gara è finita. L’ultima cosa da fare e creare una classe che sia conforme a DelegatoCorsa
class ResocontoGara:DelegatoCorsa {
func corsaIniziata(cors: GestioneCorsa, f: Corsa, a: Corsa) {
println(“La gara è Iniziata”)
}
func corsaFinita(cors: GestioneCorsa, f: Corsa, a: Corsa) {
println(“La gara è finita”)
}
}
Per poter testare questo piccolo esempio scrivete:
var provaGara = GestioneCorsa(fer: Ferrari(), aud: Audi())
provaGara.delegate = ResocontoGara ()
provaGara.gara()