Czy każdy ivar musi być własnością?

Widzę, że zaleca się wszędzie przy kodowaniu dla iOS, aby właściwości były używane do uzyskiwania dostępu do zmiennych instancji, między innymi ze względu na korzyści płynące z zarządzania pamięcią.

Ta rada mi nie odpowiada. Uważam, że używanie właściwości zamiast zwykłych starych ivars po prostu wymaga zbyt dużo kodu i nie widzę korzyści, jeśli jesteś wygodny w zarządzaniu pamięcią. Czy to naprawdę takie ważne? Jakie jest twoje podejście do zarządzania zmiennymi instancji?

Author: nevan king, 2011-02-17

4 answers

Nie jest konieczne deklarowanie właściwości dla wszystkich ivarów. Na myśl przychodzi kilka punktów:

  • jeśli ivar będzie przypisany tylko raz w ciągu życia obiektu, tak naprawdę nic nie zyskasz, deklarując właściwość. Po prostu zachowaj / skopiuj/Przypisz podczas init, a następnie zwolnij w razie potrzeby podczas dealloc.
  • jeśli ivar ma być często zmieniany, deklarowanie właściwości i zawsze używanie accesorów ułatwi unikanie zarządzania pamięcią błędy.
  • możesz zadeklarować właściwości w rozszerzeniu klasy w .plik m zamiast .H plik, jeśli właściwości i ivars mają być prywatne.
  • W przypadku iOS 4.0+, nie musisz w ogóle deklarować ivars w nagłówku, jeśli zdefiniujesz właściwość i zsyntetyzujesz Accesory.

Więc generalnie używam właściwości, ale dla rzeczy takich jak NSMutableArray, które obiekt przydziela podczas init i używa do przechowywania kilku whatevers, użyję zwykłego starego Ivara, ponieważ nigdy nie będę zmieniam Ivara.

 79
Author: Daniel Dickison,
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
2011-02-17 15:59:47

Chociaż odpowiedź Daniela jest poprawna, myślę, że pomija ważną kwestię. Mianowicie:

Uważam, że używając właściwości zamiast ze zwykłych starych ivarów wystarczy za dużo kod i nie widzę korzyści, jeśli czujesz się komfortowo z zarządzanie pamięcią.

Korzyści to spójność; spójne zarządzanie pamięcią i spójne zachowanie.

Szczególnie, te dwie linie kodu mogą mieć skrajnie różne zachowanie w czas trwania:

iVar = [foo retain];
self.iVar = foo;

Pierwszy jest bezpośrednim ustawieniem zmiennej instancji i nie będzie żadnych powiadomień o zmianach. Drugi przechodzi przez setter i w ten sposób zachowuje wszelkie modyfikacje podklasy po set i zapewnia, że obserwatorzy właściwości są powiadamiani o zmianie.

Jeśli używasz ivars bezpośrednio w swoim kodzie (wewnętrznie do klasy -- jeśli używasz ivars instancji bezpośrednio z poza tej instancji, cóż... każdy wykonawca pracujący na Twoim kodzie powinien podwoić swoje stawki ;), wtedy musisz też obsługiwać powiadomienie o zmianie ręcznie (zazwyczaj dzwoniąc willChangeValueForKey:/didChangeValueForKey) lub jawnie zaprojektuj swoją aplikację, aby uniknąć korzystania z mechanizmów, które opierają się na obserwacji wartości klucza.

Mówisz "za dużo kodu". Nie widzę tego; w powyższych dwóch linijkach kodu składnia kropki jest mniejsza. Nawet wywołanie metody setter przy użyciu tradycyjnej składni byłoby mniej kodu.

I nie obniżaj wartości w centralizacji zarządzania pamięcią; jedno przypadkowe pominięcie w niezliczonej liczbie miejsc połączeń i crash city.

 51
Author: bbum,
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
2011-02-17 17:40:50

Właściwości są tylko cukrem składni, który pozwala uniknąć pisania tych samych metod w kółko. Z właściwością masz seter, który zwalnia stary obiekt i zachowuje nowy za darmo.

 3
Author: Simone D'Amico,
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
2011-02-17 15:58:06

Dla prywatnych pól-sugeruję bezpieczne używanie direct ivars tylko dla prymitywnych typów (BOOL/int / float itp.). Znajduję dobrą praktykę owijania wszystkiego związanego z zarządzaniem pamięcią we właściwościach-nawet rzadko używanych polach. Dodatkową zaletą tego podejścia jest to, że IDE Zwykle inaczej podświetla bezpośredni dostęp do ivars, więc zawsze masz ładny rozdział prostych pól skalarnych i pól typu obiektowego.

W przeciwieństwie do tego zdecydowanie odradzam wszelkie bezpośrednie ivars w klasie public interface . Ze względu na dynamiczny charakter języka może to prowadzić do błędów uruchomieniowych, które są niezwykle trudne do znalezienia, zlokalizowania i naprawienia. Rozważmy następującą hierarchię
@interface BaseControl
...
@end

@interface Label : BaseControl
...
@end

@interface Button : BaseControl {
  @public
    BOOL enabled;
}
@end

I fragment kodu

- (void)enableAllButtons {
    NSArray *buttons = [self getAllButtons];   // expected to contain only Button instances
    for (Button *button in buttons) {
        button->enabled = YES;
    }
} 

Teraz wyobraź sobie, że gdzieś w logice-getAllButtons jest błąd i dostajesz również zwracane etykiety w tej tablicy - więc te instancje klas etykiet będą brakować przypisanego ivar. Fakt, że może być zaskakujące jest to, że-enableAllButtons będzie Nie w takim wypadku. Ale w tym momencie wewnętrzna struktura instancji etykiety jest uszkodzonai to spowoduje niezdefiniowane zachowanie i awarię, gdy zostaną użyte gdzie indziej.

Podobnie jak niektóre popularne problemy z zarządzaniem pamięcią (i ogólnie-z wiszącymi wskaźnikami) - tego rodzaju problemy są trudne do znalezienia i zlokalizowania-ponieważ pojawienie się błędu zwykle jest odległe (pod względem czasu, kodu lub przepływu aplikacji) od miejsca, powodując błąd. Ale z tym szczególny problem nawet nie masz poręcznych narzędzi (takich jak leak/zombies analyzers itp.), aby pomóc Ci zlokalizować i naprawić-nawet gdy nauczysz się, jak go odtworzyć i możesz łatwo zbadać błędny stan.

Oczywiście jeśli użyjesz @property (assign) BOOL enabled; otrzymasz łatwy do zdiagnozowania i naprawienia wyjątek w-enableAllButtons.

 1
Author: Max O,
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
2012-07-12 18:03:11