2009-05-04 10 views
7

Rozważmy następującą sytuację: wspólnyObjective-C/Cocoa: Właściwa konstrukcja dla delegatów i kontrolerów

Masz jakieś MainView w aplikacji Cocoa, załadowany z NIB, który jest kontrolowany przez MainViewController. Twój MainView zawiera kilka elementów sterujących, takich jak UILabel infoLabel. Masz również klasę delegata MyDelegate, która otrzymuje jakieś wydarzenie.

Chcesz się upewnić, że gdy MyDelegate odbiera swoje wydarzenie, infoLabel jest odpowiednio aktualizowany. Problem polega jednak na tym, że MyDelegate nie ma odniesienia do MainView lub MainViewController i nie zna etykiety.

Jednym z rozwiązań jest przekazanie odwołania do obiektu delegata o numerze MainViewController, ale jest to niepoprawne, ponieważ możesz znaleźć się w niepożądanej sytuacji, w której obiekt ma odniesienia do siebie nawzajem.

Jaki jest właściwy projekt rozwiązania tego problemu?

+0

Mam ten sam problem w tej chwili. Rozwiązaniem dla nas jest odwoływanie się. Mówisz, że to niepożądana sytuacja. Czy możesz wyjaśnić, dlaczego? – Kriem

+0

Dla mnie dwa główne powody: okrągłe odniesienia "czuć" źle; masz tendencję do ciągłego rzucania odniesienia. Mogę być całkowicie wyłączony. – Jake

+0

Wiem co masz na myśli. Nie mogę się doczekać, co inni o tym sądzą. Dobre pytanie. – Kriem

Odpowiedz

4

W nienazwanej forum dla programistów, ktoś pisze:

Tak, aby długie opowiadanie, postanowiłem, że zacznę wykorzystanie NSNotifications. Kurs online Stanforda, którego ludzie śledzili, jest prowadzony przez dwóch inżynierów Apple. Niedawno jednoznacznie powiedzieli, że NIE używają delegatów aplikacji lub zmiennych globalnych i powiedzieli, że korzystają z NSNotification, delegatów i obserwacji K-V.

Jeśli tak mówią inżynierowie Apple, zamierzam ruszyć w tym kierunku.

NSNotifications są dość pomysłowe, ponieważ tak naprawdę nie zakłócają hermetyzacji. Słuchacz słucha tylko powiadomienia i obiektu - nie sądzę, że musi wiedzieć lub obchodzić, kto go wysłał.

Tak więc w twoim przykładzie rozważałbym wysłanie delegatowi powiadomienia, że ​​etykieta uległa zmianie, lub lepiej, aby kontroler przestrzegał tej właściwości, jeśli to możliwe.

+0

Naprawdę muszę obejrzeć vidy ze Stanford. – Kriem

+0

Chociaż NSNotifications działają dobrze w tym przypadku, zdecydowanie odradzam używanie ich zbyt wiele w Twojej aplikacji. Powiadomienia są bardzo trudne do debugowania i nie zawsze wystarczy spojrzeć na kod, aby zobaczyć, kiedy i gdzie coś się strzela. Kilka słów ostrzeżenia. –

+0

Cześć Matt, rozumiem twoją troskę o NSNotifications. W związku z tym, wszelkie inne sugestie? – Jake

-1

Typowy wzorzec to, jak powiedziałeś, przekazanie wskaźnika do MainView za pośrednictwem metod delegatów. Tak więc, jeśli MainView dzwoni doSomethingWithFoo: metody jej przedstawiciel jest, chcesz zmienić tę metodę:

- (void)mainView:(MainView *)view doSomethingWithFoo:(id)foo 

i wywołać nową metodę odpowiednio. Jeśli operujesz bezpośrednio na wskaźniku MainView, nie powinieneś mieć żadnych problemów z odwołaniami cyklicznymi.

+0

Ale załóżmy, że delegat nie jest delegatem MainView, ale innego protokołu ...? – Jake

+0

Następnie użyj metody określonej w protokole? Otrzymuje powiadomienie z MainView, prawda? Być może jest jakiś istotny aspekt sytuacji, którego brakuje w pytaniu. – Chuck

+0

Załóżmy, że ustawiłem obiekt, który implementuje protokół CLManagerDelegate (Cocoa Touch) i nasłuchuje aktualizacji lokalizacji. Nie otrzymuje powiadomień z MainView, ale musi uzyskać dostęp do etykiety. – Jake

0

Wdrożyliśmy skomplikowany "Dane" - obiekt, który kontroluje prawie wszystko. Sprawdza, czy są jakieś zmiany i aktualizuje wszystkie globale.

Podczas tworzenia nowych instancji odsyłam do klasy Danych tak:

[[Button alloc] initWithData:data]]; 

Gdzie data jest Singelton Danych klasę. Teraz możemy sprawdzić, czy są potrzebne zmiany, aby zareagować.

Przyznaję, nadal wymaga to odnoszenia się, jak opisałeś. Wygląda na to, że nie ma wbudowanego prostego odnośnika parent.

2

Oto 2 opcje, które przychodzą do głowy:

  • Jeśli zdarzenie zamierza powierzyć to wysłać przez kontrolera, można mieć że metoda zwraca wartość do sterownika, aby popchnąć do widoku.

  • Można również powiązać wartość infoLabel z jakimś kluczem (używając, powiedzmy, wiązań kakao lub po prostu nieprzetworzonych wartości klucz-wartość). Obiekt związany (który może być delegatem lub jakimś innym obiektem modelu) mógłby po prostu zaktualizować klucz związany, który przesyła wartość do elementu infoLabel. Na przykład możesz powiązać członka "delegata" delegata z wartością infoLabel. Kiedy delegat otrzyma zdarzenie, może zaktualizować członka informacji, a widok się zmieni. Rzeczywista wiązania samo może się wydarzyć w IB (jeśli pełnomocnik jest nib) lub sterownika (który ma odniesienie do widoku i pełnomocnika.)

Powstały roztwór jest w zasadzie kolisty odniesienia ale który wydaje mi się bardziej czysty.

+0

Tak, to na pewno najczystsze rozwiązanie do tej pory. – Jake

Powiązane problemy