Jak stworzyć prawdziwą prywatną zmienną instancji?

Chcę utworzyć zmienną instancji, do której nie można uzyskać dostępu z zewnątrz. Czy coś takiego jest możliwe w objective-c? Pamiętam, że Apple ma prywatne zmienne i takie tam, ale jeśli ludzie o nich wiedzą, mogą z nich korzystać. Apple nazywa to "prywatnym API", ale oczywiście inni mogą uzyskać dostęp do tych rzeczy, jeśli dowiedzą się, co tam jest.

Do tej pory wierzyłem, że coś takiego tworzy prywatną zmienną instancji:

@interface MyClass : NSObject {
    CGFloat weight;
}

No @ property, no @synthesize, just powyższej deklaracji.

Wiem również, że Apple dodaje _inFrontOfTheirPrivateInstanceVariables, ale powiedzieli gdzieś, że nie lubią widzieć, jak inni to robią, ponieważ mogą zastąpić przypadkowo Ukryte zmienne instancji podczas robienia tego.

Co to za sztuczka?

Author: Quinn Taylor, 2009-08-11

7 answers

Możesz użyć słowa kluczowego @private wewnątrz {}, aby wszystkie kolejne deklaracje zmiennych były prywatne. Domyślna widoczność to @protected (która jest podobna do protected w Javie) i ogólnie działa dobrze. Musisz zadeklarować zmienną jako @public, aby była bezpośrednio dostępna poza klasą.

Ta dokumentacja Apple zawiera więcej szczegółów na temat zmiennego zakresu i widoczności.

Istnieje również różnica między "prywatnym API" a prywatnym zmienne. W Objective-C nie można uczynić metod prywatnych-każdy może wywołać dowolną metodę. Istnieje kilka sposobów tworzenia "tajnych" metod, ale jest to nieco poza zakresem tego pytania. Oto kilka powiązanych pytań:

Jeśli chodzi o wiodącą _ przed zmiennymi, należy pamiętać, że Apple również rezerwuje ten przedrostek dla metod "prywatnych". Najlepszym sposobem na uniknięcie problemów jest użycie normalnych konwencji nazewnictwa dla własnych zmiennych i metod. Jeśli jednak nie podklasujesz czegoś Z Cocoa (innego niż NSObject), możesz być pewien, że nie napotkasz problemów.

 60
Author: Quinn Taylor,
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
2017-05-23 12:02:12

Dzięki nowemu kompilatorowi LLVM dostępnemu w XCode 4 i nowszych, możesz zadeklarować @private zmienne w domyślnych kategoriach wewnątrz swojej implementacji (.m) plik:

@interface ClassName()
{
@private
// private variables here
}
@end

@implementation ClassName
// you can use private variables here
@end

Uważam to za wygodne, ponieważ nienawidzę zanieczyszczeń, które prywatne zmienne wprowadzają do moich plików nagłówkowych.

 31
Author: Johannes Rudolph,
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-04-30 14:56:10

Możesz zdefiniować prywatne metody, po prostu mając je tylko w implementacji@, a nie w interfejsie@.

Podobnie można definiować prywatne zmienne instancji wewnątrz anonimowego bloku na początku implementacji @ - tak jak w przypadku publicznych ivarów wewnątrz interfejsu@.

Zobacz poniższy przykład.
@interface EXClass : NSObject
{
uint8_t publicInteger;
float publicFloat;
}

-(void)publicMethod;
@end

@implementation EXClass
{
uint8_t privateInteger;
float privatefloat;
}

-(BOOL)privateMethod {
return FALSE;
}

Pamiętaj, że metody objective-C są wysyłane jako wiadomości w czasie wykonywania (zamiast wiązania czasu kompilacji C++), więc respondsToSelector: nadal zwraca true i performSelector: nadal wywoła metodę. Ivarowie będą w pełni prywatni.

Jeśli tworzysz bibliotekę, teoretycznie nikt nie wiedziałby o metodach, których nie zadeklarowałeś w plikach nagłówkowych.

 9
Author: stef,
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-08-19 19:27:43

Wszystkie Ivary w Objective-C są domyślnie chronione. Jeśli nie napiszesz metod dostępu, inne klasy nie będą w stanie zobaczyć zmiennych.

Dwa wyjątki to kategorie i podklasy.

 3
Author: kubi,
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-08-11 19:45:39

Dokumenty Apple do nazywania zmiennych instancji nie ostrzegają przed używaniem podkreślenia w nazwach zmiennych instancji, tak jak robią to dokumenty metody prywatnej.

Nazewnictwo zmiennych instancji i typów danych

Pamiętam też rozmowę Wil Shipley ' a z kilkoma innymi programistami OS X. Ze względu na sposób działania kompilatora Obj-C, gdyby Apple dodało nową zmienną instancji do klasy w swoich frameworkach, spowodowałoby to, że wszystkie aplikacje używanie tych frameworków do rekompilacji. Jeśli chodzi o istniejące wcześniej zmienne instancji, powinieneś otrzymać ostrzeżenie, gdy nadepniesz na jedną z nich.

 2
Author: criscokid,
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-07-21 23:58:40

Na przykład, w aplikacji paintgl firmy Apple widziałem następujące użycie]}

W .m file

@interface MyClass (private)
  - (void) privateMethod();
  @property(...) myProperty;
@end

Disclaimer: przykładowa aplikacja ma tylko deklaracje metody, widziałem deklarację własności prywatnej w tym wątku

 2
Author: Ege Akpinar,
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
2017-05-23 12:09:37

Możesz nie stworzyć prawdziwą prywatną zmienną instancji. Objective-C jest językiem dynamicznym i dlatego możliwy jest dostęp do dowolnej zmiennej (nawet @ private).

Moje najlepsze podejście:

Użyj go w bloku implementacji Ciebie .plik M. Wtedy nie jest widoczny i blokuje KVC, tak że KVC nie będzie działać

@implementation ClassName {
    // default to @protected
    // but the subclasses can't see ivars created in the implementation block
    float number;
}

+ (BOOL)accessInstanceVariablesDirectly {
    return NO; // no KVC
}

@end
 1
Author: Binarian,
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-01-03 13:14:47