iPhone & iPad developer: NSNotification, NSNotificationCenter
Občas velmi užitečným mechanismem pro předávání zpráv mezi dvěma objekty může být použití notifikací.
Nepřímé předávání zpráv, možná bychom mohli nazvat jako Signal Handler, je mechanismus, kdy potřebujeme kontaktovat jiný objekt (nebo skupinu objektů), který není s aktuálním objektem, nebo modulem přímo propojen, a nemůžeme jej tedy
jedndouše kontaktovat. V podstatě můžeme přes notifikace kontaktovat objekty nebo moduly, které:
- nejsou propojeny s aktuálním modulem a nechceme s nimi navazovat připojení
- nevíme který objekt danou aktuální notifikaci potřebuje
NSNotificationCenter nefunguje tak, že kontaktujeme předem určený objekt, ale pouze pošleme zprávu do notifikačního centra, a všechny objekty, které danou zprávu dokáží zpracovat ji musí očekávat. Zpráva není odesílána danému přijemci, ale obsahuje pouze název, dle kterého ji objekt přijme nebo nepřijme, podle registrovaného handleru na danou zprávu.
Podívejme se na reálný přiklad, který není možná ideální, ale bude správně simulovat použitelnost NSNotification:
Máme aplikaci, která obsahuje mapu, k dané mapě existuje nastavení, kde volíme zobrazení mapy:
Nastavení otevíráme pouze přes IBAction:
1 2 3 4 5 6 |
-(IBAction)openSettings:(id)sender{ AppSettings *next = [[AppSettings alloc] initWithNibName:nil bundle:nil]; next.modalTransitionStyle = UIModalTransitionStylePartialCurl; [self presentModalViewController:next animated:YES]; } |
Třída AppSettings není nijak s aktuální třídou propojena, ale obsahuje UISegmentedControl, kterým můžeme přepínat zobrazení mapy.
Pro přepnutí zobrazení mapy si vytvoříme IBAction, která bude pouze vytvářet post do NSNotificationCenter:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
- (IBAction)changeMapType:(id)sender{ int control = ((UISegmentedControl *)sender).selectedSegmentIndex; switch (control) { case 0: [self dismissViewControllerAnimated:YES completion:^{ [[NSNotificationCenter defaultCenter] postNotificationName:@"showMapNormal" object:nil]; }]; break; case 1: [self dismissViewControllerAnimated:YES completion:^{ [[NSNotificationCenter defaultCenter] postNotificationName:@"showMapSatelite" object:nil]; }]; break; default: [self dismissViewControllerAnimated:YES completion:^{ [[NSNotificationCenter defaultCenter] postNotificationName:@"showMapHybrid" object:nil]; }]; break; } } |
Tato funkce, po kliknutí na tlačítko volá postNotificationName, a pošle zprávu do NSNotificationCenter, kde si ji mohou další objekty odchytit, podle jejího názvu.
V daném objektu poté pouze registrujeme notifikace, které naslouchají na dané zprávě, například:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
-(void)registerNotifications{ //notification satelite map [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showMapSatelite) name:@"showMapSatelite" object:nil]; //notification normal map [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showMapNormal) name:@"showMapNormal" object:nil]; //notification hybrid map [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showMapHybrid) name:@"showMapHybrid" object:nil]; } - (void)viewDidLoad { [self registerNotifications]; } |
Po vyvolání notifikace bude objekt naslouchat nad NSNotificationCenter a čekat na dané zprávy, pokud se centru objeví, přizpůsobí tomu běh aplikace, v tomto konkrétním případě volá obslužné funkce.