English site
  • Delegati i protokoli

    Objavio: Luka Gabric, 31. 05. 2010. u kategoriji iPhone development

    demystifying_photo_2

    Delegati i protokoli su vrlo korisni koncepti objektno orijentiranog programiranja. Često se koriste zajedno, pogotovo u situacijama kada je potrebno određenom informacijom obavijestiti neki nepoznati objekt, odnosno objekt kojemu se još ne poznaje klasa.

    Pretpostavimo da imamo nekoliko klasa koje je potrebno obavijestiti o nekom događaju. Kod događaja, klase se trebaju obavijestiti nekim rezultatom koji će se koristiti u različitim implementacijama tih klasa.

    Prvo trebamo izraditi protokol, nazovimo ga MojProtokol koji će se koristiti za definiranje metode koja će se pozivati nakon događaja. Pretpostavimo da je željeni rezultat cijeli broj koji se nakon događaja treba proslijediti svim delegatima. Nije bitno kako će delegati implementirati tu metodu, bitno je samo da implementiraju željeni protokol.

    Protokol.h:

    1
    2
    3
    4
    5
    
    @protocol MojProtokol
     
    - (void) dobiveniParametar:(int)broj;
     
    @end

    Sada je potrebno izraditi klasu OperacijskaKlasa koja će obavijestiti delegate s određenim rezultatom.

    OperacijskaKlasa.h:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    #import "Protokol.h"
     
    @interface OperacijskaKlasa : NSObject 
    {
     
    	id < MojProtokol > delegati;
    	NSMutableArray *nizDelegata;
     
    }
     
     
    - (void) registrajDelegata:(id)delegat;
    - (void) obavijestiDelegate;
     
     
    @end

    OperationsClass.m

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    
    #import "OperacijskaKlasa.h"
     
     
    @implementation OperacijskaKlasa
     
    - (id) init
    {
    	self = [super init];
    	if (self != nil) 
    	{
    		nizDelegata = [[NSMutableArray alloc] init];
    	}
    	return self;
    }
     
     
    - (void) registrajDelegata:(id)delegat
    {
    	if ( ![nizDelegata containsObject: delegat] )
    		[nizDelegata addObject:delegat];
    }
     
     
    - (void) obavijestiDelegate
    {
    	for ( id < MojProtokol > delegat in nizDelegata ) 
    	{
    		[delegat dobiveniParametar:10];
    	}
    }
     
     
    @end

    U konstruktoru se klase postavlja niz koji će pratiti registrirane delegate, odnosno delegate koje će se obavijestiti o događaju. Korištenje protokola vrlo je važno u ovom slučaju jer se ne zna o instanci koje klase je riječ. Bitno je da ta instanca implementira MojProtokol. Ukoliko je to slučaj, bit će moguće pozivanje metode dobiveniParametar tog objekta budući da on implementira protokol MojProtokol, a time i metodu dobiveniParametar deklariranu u protokolu.

    Sljedeći korak je kreiranje dvije klase delegata, DelegatKlasa i DrugiDelegatKlasa, koje će implementirati navedeni protokol. Implementacija protokola bit će različita za te dvije klase.

    DelegatKlasa.h:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    #import "Protokol.h"
    #import "OperacijskaKlasa.h"
     
     
    @interface DelegatKlasa : NSObject  < MojProtokol > {
     
    }
     
     
    - (id) izradiSInstancomOperacijskeKlase:(OperacijskaKlasa *)instancaOperacijskeKlase;
     
     
    @end

    DelegatKlasa.m:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    
    #import "DelegatKlasa.h"
    #import "OperacijskaKlasa.h"
     
     
    @implementation DelegatKlasa
     
     
    - (id) izradiSInstancomOperacijskeKlase:(OperacijskaKlasa *)instancaOperacijskeKlase
    {
    	self = [super init];
    	if (self != nil) 
    	{
    		[instancaOperacijskeKlase registrajDelegata:self];
    	}
    	return self;
    }
     
     
     
    - (void) dobiveniParametar:(int)broj
    {
    	NSLog(@"Vrijednost = %d", broj);
    }
     
     
    @end

    DelegatKlasa implementira protokol MojProtokol, a u konstruktoru se registrira kao delegat u klasi OperacijskaKlasa. Protokol je implementiran metodom dobiveniParametar.

    Druga se klasa zove DrugaKlasaDelegata.

    DrugaKlasaDelegata.h:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    #import "Protocol.h"
    #import "OperacijskaKlasa.h"
     
     
    @interface DrugaKlasaDelegata : NSObject < MojProtokol > {
     
    }
     
     
    - (id) izradiSInstancomOperacijskeKlase:(OperacijskaKlasa *)instancaOperacijskeKlase;
     
     
    @end

    DrugaKlasaDelegata.m:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    
    #import "DrugaKlasaDelegata.h"
     
     
    @implementation DrugaKlasaDelegata
     
     
    - (id) izradiSInstancomOperacijskeKlase:(OperacijskaKlasa *)instancaOperacijskeKlase
    {
    	self = [super init];
    	if (self != nil) 
    	{
    		[instancaOperacijskeKlase registrajDelegata:self];
    	}
    	return self;
    }
     
     
    - (void) dobiveniParametar:(int)broj
    {
    	int nekaVrijednost = broj + 15;
     
    	NSLog(@"Potpuno druga implementacija: nekaVrijednost = %d", nekaVrijednost);
    }
     
     
    @end

    DrugaKlasaDelegata implementira protkol MojProtokol te se u konstruktoru, isto kao KlasaDelegate, registrira kao delegat instanci klase OperacijskaKlasa. Implementacija protokola MojProtokol klase DrugaKlasaDelegata, metoda dobiveniParametar, razlikuje se od implementacije u klasi DelegatKlasa.

    Prikazani kod može se implementirati tako da se prvo napravi instanca klase OperacijskaKlasa.

    1
    
    OperacijskaKlasa *operacijskaInstanca = [[OperacijskaKlasa alloc] init];

    Zatim se izrađuje instanca klase DelegatKlasa koja se inicijalizira s instancom klase OperacijskaKlasa.

    1
    
    DelegatKlasa *instancaDelegatKlase = [[DelegatKlasa alloc] izradiSInstancomOperacijskeKlase:operacijskaInstanca];

    U konstruktoru klase DelegatKlasa odvija se registracija delegata u operacijskojInstanci.

    Delegati se mogu obavijestiti na sljedeći način:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    NSLog(@"Prva obavijest (samo jedan delegat u popisu)");
    [operacijskaInstanca obavijestiDelegate];
    NSLog(@"====================================================");
     
    Rezultat:
     
    Prva obavijest (samo jedan delegat u popisu)
    Vrijednost = 10
    ====================================================

    Instanca klase OperacijskaKlasa šalje obavijest svim delegatima koji su se registrirali. U nizu se trenutno nalazi jedan delegat – instancaDelegatKlase.

    Dodavanjem još jednog delegata, onog klase DrugaKlasaDelegata, i pozivanjem obavijestiDelegate metode dobit ćemo sljedeći rezultat:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
     DrugaKlasaDelegata *drugaInstancaDelegata = [[DrugaKlasaDelegata alloc] izradiSInstancomOperacijskeKlase:operacijskaInstanca];
     
    NSLog(@"Druga obavijest (oba delegata u popisu)");
    [operacijskaInstanca obavijestiDelegate];
    NSLog(@"====================================================");
     
    Rezultat:
     
    Druga obavijest (oba delegata u popisu)
    Value = 10
    Potpuno druga implementacija: nekaVrijednost = 25
    ====================================================

    Prema rezultatima, može se vidjeti da su oba delegata obaviještena budući da su se registrirali kao delegati. Oba objekta su dobili obavijest pozivanjem iste metode s istim parametrom, ali su implementacije te metode potpuno drugačije u svakoj od klasa.

    Delegacija je često korišten uzorak u objektno-orijentiranom programiranju uz koji se često koriste protokoli koji omogućavaju komunikaciju s instancama do ovog trenutka nepoznatih klasa. Bitno je samo da te klase implementiraju definirani protokol.

  • Leave a Reply