Objective - C static, extern, public variables

Chcę mieć zmienną, do której mogę uzyskać dostęp w dowolnym miejscu, importując plik nagłówkowy, ale chcę również, aby była statyczna w tym sensie, że istnieje tylko jedna z nich. W moim .m file, i specify

static BOOL LogStuff = NO;

I w metodzie initialize ustawiłem wartość logowania:

+ (void)initialize
{
    LogStuff = ... //whatever
}

Jednak chcę mieć dostęp do mojej zmiennej w dowolnym miejscu, importując .plik h więc chcę zrobić coś takiego:

static extern BOOL LogStuff;
Ale nie wolno mi tego robić. Czy można zrobić to, co jestem próbujesz to zrobić? Dzięki
Author: JPC, 2011-10-04

5 answers

static w Objective-C oznacza inną rzecz niż static w klasie C++, w kontekście statycznych członków danych klasy i statycznych metod klasy. W C i Objective-C zmienna lub funkcja static w globalnym zasięgu oznacza, że symbol ten ma wewnętrzne powiązanie .

Wewnętrzne powiązanie oznacza, że ten symbol jest lokalny dla bieżącej jednostki tłumaczenia , która jest obecnie kompilowanym plikiem źródłowym (.c lub .m) i wszystkimi plikami nagłówkowymi, które rekurencyjnie zawiera. Ten symbol nie może być odwołany z innej jednostki tłumaczenia, a inne symbole z wewnętrznym połączeniem mogą być używane w innych jednostkach tłumaczenia o tej samej nazwie.

Tak więc, jeśli Masz plik nagłówka deklarujący zmienną jako static, każdy plik źródłowy, który zawiera ten nagłówek, otrzymuje oddzielną zmienną globalną-Wszystkie odniesienia do tej zmiennej w jednym pliku źródłowym będą odnosiły się do tej samej zmiennej, ale odniesienia w różnych plikach źródłowych będą odnosiły się do różne zmienne.

Jeśli chcesz mieć jedną zmienną globalną, nie możesz mieć jej w klasie scope, jak w C++. Jedną z opcji jest utworzenie zmiennej globalnej z z linkiem zewnętrznym : zadeklaruj zmienną za pomocą słowa kluczowego extern w pliku nagłówkowym, a następnie w jeden plik źródłowy, zdefiniuj ją w globalnym zasięgu bez słowa kluczowego extern. Powiązania wewnętrzne i zewnętrzne wzajemnie się wykluczają-nie możesz mieć zmiennej zadeklarowanej zarówno jako extern, jak i static.

Alternatywą, jak zasugerował Panos , byłoby użycie metody klasy zamiast zmiennej. To utrzymuje funkcjonalność w zakresie klasy, co ma więcej sensu semantycznie, i możesz również zrobić to @private, jeśli chcesz. Dodaje to marginalną karę za wydajność, ale jest bardzo mało prawdopodobne, aby było to wąskie gardło w aplikacji(jeśli podejrzewasz, że tak jest, zawsze najpierw profil).

 121
Author: Adam Rosenfield,
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:10:26

Jeśli LogStuff jest statycznym polem klasy, może możesz zaimplementować statyczny getter i setter?

+ (void)setLogStuff:(BOOL)aLogStuff;
+ (BOOL)logStuff;
 4
Author: Panos,
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-10-04 01:14:52

Zadeklaruj to extern BOOL w swoim pliku nagłówkowym. Pliki, które #import twój nagłówek nie wiedzą lub nie dbają o to, czy zewnętrzny symbol jest statyczny, czy nie.

 3
Author: NSResponder,
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-10-04 01:16:03

Oddzielna zmienna globalna (jedna na plik źródłowy):

// .h
static NSString * aStatic;

//.m
static NSString * aStatic = @"separate";

Unikalna zmienna globalna:

// .h
extern NSString * anExtern;

// .m
NSString * anExtern = @"global";
 1
Author: SwiftArchitect,
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
2015-07-28 20:50:06

Normalnie używam tego układu dla moich statyk:

NSMutableArray *macroArray;
BOOL keepMacro;

+ (void) startMacro
{
    if (macroArray == nil)
    {
        macroArray = [[NSMutableArray alloc] initWithCapacity:100];
    }

    [macroArray removeAllObjects];
    keepMacro = YES;
}

To jest startMacro komenda w mojej aplikacji. Zarówno Bool, jak i macroArray są statyczne, ale zauważ, że nie są zadeklarowane static lub extern.

Może to nie jest najlepsza praktyka, ale tym się zajmuję.
 0
Author: The Lazy Coder,
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-11-03 17:04:05