Do czego służy parametr kontekstowy w obserwacji wartości klucza
Jakie jest zastosowanie parametru kontekstowego w następującej metodzie, która jest używana do rejestracji powiadomień o wartości klucza. Dokumentacje po prostu oznacza to jako dowolny zestaw danych.
addObserver:self forKeyPath:@"selectedIndex" options:NSKeyValueObservingOptionNew context:nil
Czy ktoś może rzucić trochę światła na to, jaki jest cel ... 1 answers
Mam nadzieję, że to wyjaśnienie nie jest zbyt abstrakcyjne, aby zrozumieć.
Załóżmy, że tworzysz klasę MyViewController
, która jest podklasą UIViewController
. Nie masz kodu źródłowego UIViewController
.
Teraz zdecydujesz się MyViewController
użyć KVO do obserwowania zmian w center
właściwości self.view
. Więc należycie dodajesz siebie jako obserwatora:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.view addObserver:self forKeyPath:@"center" options:0 context:NULL];
}
- (void)viewDidDisappear:(BOOL)animated {
[self.view removeObserver:self forKeyPath:@"center"];
[super viewDidDisappear:animated];
}
Problem polega na tym, że nie wiesz, czy UIViewController
rejestruje się również jako obserwator self.view
's center
. Jeśli tak, to możesz mieć dwa problemy:
- możesz zostać wywołany dwa razy, gdy zmieni się centrum widoku.
- kiedy usuniesz siebie jako obserwatora, możesz również usunąć
UIViewController
rejestrację KVO.
Potrzebujesz sposobu zarejestrowania siebie jako obserwatora, który jest odróżnialny od UIViewController
rejestracji KVO. Tutaj pojawia się argument context
. Musisz przekazać wartość context
, która jest absolutnie pewna UIViewController
jest , a nie używaną jako argument context
. Kiedy ty Wyrejestruj się, używasz tego samego context
ponownie, aby usunąć tylko swoją rejestrację, a nie rejestrację UIViewController
. W metodzie observeValueForKeyPath:ofObject:change:context:
musisz sprawdzić context
, aby sprawdzić, czy wiadomość jest dla Ciebie, czy dla Twojej superklasy.
Jednym ze sposobów na upewnienie się, że używasz context
, którego nic innego nie używa, jest utworzenie static
zmiennej w MyViewController.m
. Użyj go podczas rejestracji i wyrejestrowania, w ten sposób:
static int kCenterContext;
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.view addObserver:self forKeyPath:@"center" options:0 context:&kCenterContext];
}
- (void)viewDidDisappear:(BOOL)animated {
[self.view removeObserver:self forKeyPath:@"center" context:&kCenterContext];
[super viewDidDisappear:animated];
}
Następnie w metodzie observeValueForKeyPath:...
, sprawdź to tak:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context
{
if (context == &kCenterContext) {
// This message is for me. Handle it.
[self viewCenterDidChange];
// Do not pass it on to super!
} else {
// This message is not for me; pass it on to super.
[super observeValueForKeyPath:keyPath ofObject:object
change:change context:context];
}
}
Teraz jesteś gwarantuję, że nie będzie ingerować w KVO Twojej superklasy, jeśli to zrobi. A jeśli ktoś stworzy podklasę MyViewController
, która również używa KVO, nie będzie ingerować w twoje KVO.
Zauważ również, że możesz użyć innego kontekstu dla każdej ścieżki kluczowej, którą obserwujesz. Następnie, gdy system powiadomi Cię o zmianie, Możesz sprawdzić kontekst zamiast sprawdzania kluczowej ścieżki. Testowanie równości wskaźników jest trochę szybsze niż sprawdzanie równości łańcuchów. Przykład:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context
{
if (context == &kCenterContext) {
[self viewCenterDidChange];
// Do not pass it on to super!
} else if (context == &kBackgroundColorContext) {
[self viewBackgroundDidChange];
// Do not pass it on to super!
} else if (context == &kAlphaContext) {
[self viewAlphaDidChange];
// Do not pass it on to super!
} else {
// This message is not for me; pass it on to super.
[super observeValueForKeyPath:keyPath ofObject:object
change:change context:context];
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-21 20:26:14