Właściwości i zmienne instancji w Objective-C

Jestem raczej zdezorientowany co do właściwości i zmiennych instancji w Objective-C.

Jestem w połowie drogi do "Cocoa Programming for Mac OS X" Aarona Hillegassa i wszystko jest logiczne. Zadeklarowałbyś klasę coś takiego:
@class Something;

@interface MyClass : NSObject {
    NSString *name;
    NSArray *items;

    Something *something;

    IBOutlet NSTextField *myTextField;
}

@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSArray *items;
  • Ponieważ inne obiekty muszą manipulować naszymi zmiennymi instancji name i items, używamy @property/@synthesize Aby wygenerować dla nich accessory/mutatory. W naszej klasie nie używamy accessorów / mutatorów-po prostu wchodzimy w interakcję z zmienna instancyjna bezpośrednio.

  • something jest tylko zmienną instancyjną, której będziemy używać w naszej klasie, a ponieważ nikt inny nie musi jej używać, nie tworzymy dla niej pary accesorów i mutatorów.

  • Musimy wejść w interakcję z polem tekstowym w naszym interfejsie, więc deklarujemy IBOutlet dla niego, łączymy je i kończymy.

Wszystko bardzo logiczne.

Jednak w świecie iPhone ' a wszystko wydaje się być inne. Ludzie deklarują właściwości dla każdej pojedynczej zmiennej instancji, deklaruj właściwości dla IBOutlets i używaj accesorów / mutatorów do interakcji ze zmiennymi instancji wewnątrz klasy (np. zapisaliby [self setName:@"Test"] zamiast name = @"Test").

Dlaczego? Co się dzieje? Czy te różnice są specyficzne dla iPhone ' a? Jakie są zalety deklarowania właściwości dla wszystkich zmiennych instancji, deklarowania właściwości dla IBOutlets i używania accesorów / mutatorów wewnątrz własnej klasy?

Author: Steve Harrison, 2009-10-12

5 answers

W świecie iPhone 'a nie ma garbage collector' a. Będziesz musiał ostrożnie zarządzać pamięcią z liczeniem referencji. Mając to na uwadze, rozważ różnicę między:

name = @"Test";

I

self.name = @"Test";
// which is equivalent to:
[self setName: @"Test"];

Jeśli bezpośrednio ustawisz zmienną instancji, bez uprzedniego rozważenia, stracisz odniesienie do poprzedniej wartości i nie możesz dostosować jej liczby zachowań(powinieneś mieć releaseD ręcznie). Jeśli uzyskasz do niego dostęp za pośrednictwem nieruchomości, będzie on obsługiwany automatycznie dla Ciebie, wraz z zwiększeniem liczby zatrzymań nowo przypisanego obiektu.

[3]}podstawowe pojęcie nie jest specyficzne dla iPhone ' a, ale staje się kluczowe w środowisku bez garbage collector.
 29
Author: Mehrdad Afshari,
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
2009-10-11 22:33:03

Właściwości są używane do generowania accesorów, na przykład zmiennych, nie dzieje się magia.

Możesz zaimplementować te same accessory ręcznie.

Można znaleźć w książce Aarona Hillegassa przykłady 3 strategii zarządzania pamięcią dla zmiennych członkowskich. Są assign/copy/retain. Wybierz jedną z nich jako wymaganą dla danej zmiennej.

Zakładam, że rozumiesz zarządzanie pamięcią w Objective-C... [[9]}Accessory ukrywają złożoność i różnice zarządzanie pamięcią dla każdej zmiennej.

Na przykład:

name = @"Test"

Jest prostym przydziałem, name posiada teraz odniesienie do NSString @"Test". Możesz jednak zdecydować się na użycie copy lub retain. Bez względu na to, którą wersję zarządzania pamięcią wybrałeś accessor ukrywa złożoność i zawsze uzyskujesz dostęp do zmiennej za pomocą (lub podobnej):

[self setName:@"Test"] 
[self name]

Teraz setName: może użyć assign/copy or retain i nie musisz się o to martwić.

Zgaduję, że samouczki iPhone ' a używają właściwości, aby ułatwić nowe Programiści przeskoczyć przez zarządzanie pamięcią (nawet jeśli jest to przydatne do generowania odpowiednich accesorów z właściwościami, a nie implementować je ręcznie za każdym razem).

 6
Author: stefanB,
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
2009-10-11 23:21:26
Jednak w świecie iPhone ' a wszystko wydaje się być inne. Ludzie deklarują właściwości dla każdej pojedynczej zmiennej instancji, deklarują właściwości dla IBOutlets i używają accesorów / mutatorów do interakcji ze zmiennymi instancji w klasie (np. zapisują [self setName:@"Test"] zamiast name = @"Test").
To nie jest specyficzne dla iPhone ' a. Z wyjątkiem metod init i metody dealloc, dobrą praktyką jest zawsze używanie swoich accesorów. Główną zaletą, zwłaszcza na Macu (z wiązaniami Cocoa), czy korzystanie z accesorów oznacza bezpłatne powiadomienia KVO.

Powodem, dla którego ludzie "deklarują właściwości dla każdej pojedynczej zmiennej instancji" jest najprawdopodobniej to, że wszystkie ich zmienne instancji są rzeczami, które chcą ujawnić jako właściwości. Gdyby mieli coś, co chcieliby zachować prywatnie, nie zadeklarowaliby właściwości dla tego w pliku nagłówkowym. (Mogą jednak stworzyć dla niego właściwość w rozszerzeniu klasy w pliku implementacji, w celu uzyskania wspomnianego wyżej darmowego KVO powiadomienia.)

Deklarowanie właściwości dla punktów sprzedaży jest moim zdaniem przesadą. Nie widzę w tym sensu. Jeśli nie tworzysz właściwości, nib loader ustawi wylot za pomocą bezpośredniego dostępu do zmiennych instancji, co jest w sam raz dla tego zadania.

 3
Author: Peter Hosey,
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
2009-10-12 04:55:29

Sugerowałbym, że współczesny rozwój podjął bardzo silną próbę zidentyfikowania, zdefiniowania i zastosowania najlepszych praktyk.

Wśród tych najlepszych praktyk znajdujemy ciągłość i spójność.

Oprócz argumentowania o używaniu accesorów w metodach init i dealloc, Accesory powinny być ogólnie używane przez cały czas (wewnątrz i na zewnątrz klasy) dla korzyści, które oferują, w tym enkapsulacja , polimorficzne implementacje var (które pozwalają na abstrakcję i refaktoryzacji) oraz w celu ułatwienia tych najlepszych praktyk ciągłości i spójności. Podstawowe korzyści płynące z języka zorientowanego obiektowo wchodzą w grę, gdy robi się rzeczy w ten sposób i wykorzystuje pełnię możliwości języka. Zawsze bycie konsekwentnym w swoim kodowaniu jest często wymienianą poniżej korzyścią, o czym zwykle zaświadczy każdy starszy programista.

 2
Author: JRT,
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
2010-09-26 04:15:19

Możesz pisać tak

//MyClass.h

@class Something;

@interface MyClass : NSObject 

@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSArray *items;

@end 

//MyClass.m
@interface MyClass() 

@property (nonatomic, strong) IBOutlet NSTextField *myTextField;
@property (nonatomic, strong) Something *something;

@end
 0
Author: Shafraz Buhary,
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
2013-03-18 05:31:29