Pull to refresh

MSLibrary. ПРОСТО: объявляем глобальные переменные с помощью класса singleton, для iOS и не только…

Reading time 3 min
Views 3K
Разработчики библиотеки MSLibrary for iOS продолжают серию очень компактных статей, посвященных тому как ПРОСТО реализовать ту или иную функцию. Никакой теории, только практика…

Итак, как правильно объявить глобальные переменные? Под глобальными мы понимаем переменные, объявленные на внешнем уровне (не static) и имеющие глобальное время жизни.

Если мы объявим переменную в одном из заголовочных файлов, например в файле MyClass.h таким, казалось бы логичным, образом:

NSString *myGlobalVariable;

а затем импортируем файл MyClass.h с помощью директивы #import в несколько файлов, например, MyClass1.h, MyClass2.h, MyClass3.h и MyClass4.h, то в результате с большой вероятностью получим примерно такое сообщение об ошибке:

duplicate symbol _myGlobalVariable in:
    /Users/L/Library/Developer/Xcode/DerivedData/…/MyClass.o
    /Users/L/Library/Developer/Xcode/DerivedData/…/MyClass1.o
duplicate symbol _myGlobalVariable in:
    /Users/L/Library/Developer/Xcode/DerivedData/…/MyClass.o
    /Users/L/Library/Developer/Xcode/DerivedData/…/MyClass2.o
duplicate symbol _myGlobalVariable in:
    /Users/L/Library/Developer/Xcode/DerivedData/…/MyClass.o
    /Users/L/Library/Developer/Xcode/DerivedData/…/MyClass3.o
duplicate symbol _myGlobalVariable in:
    /Users/L/Library/Developer/Xcode/DerivedData/…/MyClass.o
    /Users/L/Library/Developer/Xcode/DerivedData/…/MyClass4.o

ld: 4 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Произойдет это по тому, что в результате импорта переменная myGlobalVariable будет объявлена в каждом из подключенных файлов.

Можно объявить глобальную переменную используя «волшебное» слово extern. В этом случае, скорее всего, мы избежим сообщения об ошибке, но для переменных с глобальным временем жизни и областью видимости — все пространство приложения, существует опасность попытки одновременного изменения ее значения из разных потоков, от чего extern не может дать гарантированной защиты. К сожалению, неопытные программисты не учитывают этого важного факта. Extern можно безопасно использовать при объявлении глобальных констант, в этом случае проблем не возникает.

Нам надо объявить глобальную переменную таким образом, чтобы она не дублировалась ни при каких обстоятельствах. Для решения этой нехитрой задачи достаточно вспомнить что же может существовать в программе только в единственном экземпляре? Правильно, это — синглтон. Глобальную переменную можно задать с помощью класса синглтон (singleton), а точнее как его свойство (property). О достоинствах такого подхода написано много литературы и все интересующиеся могут почитать об этом, а также о том в каких случаях эти достоинства проявляются в полной мере. Наша задача — показать как это делается.

Паттерн Синглтон: Проверяет, что есть только один экземпляр класса и обеспечивает единую точку доступа к нему.(«Design Patterns» GoF (Addison-Wesley, 1994)).

Ниже пример кода — создаем класс сингтон, например, GlobalVariable и добавляем ему свойство myGlobalVariable, которое и будет нашей глобальной переменной:

Заголовочный файл, GlobalVariable.h

#import <Foundation/Foundation.h>;

@interface GlobalVariable : NSObject

@property(nonatomic, strong) NSString *myGlobalVariable;

+(instancetype)sharedGlobalVariable;

@end

Файл GlobalVariable.m

#import "GlobalVariable.h"

@implementation GlobalVariable

@synthesize myGlobalVariable;

+(instancetype)sharedGlobalVariable {
    static id _singletonInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
       _singletonInstance = [[super allocWithZone:NULL] init];
    });
   return_singletonInstance;
}
+(id) allocWithZone:(NSZone*)zone {
    return [self sharedGlobalVariable];
}
-(id) copyWithZone:(NSZone*)zone {
    return self;
}

Обращение к переменной выглядит следующим образом:

[GlobalVariable sharedGlobalVariable].myGlobalVariable;

Для удобства можно использовать макрос:

#define MY_GLOBAL_VARIABLE [GlobalVariable sharedGlobalVariable].myGlobalVariable;

Функция dispatch_once_t отвечает за потокобезопасность данной реализации кода.

Как видите вопрос решается всего в несколько простых строк, а при использовании библиотеки MSLibrary for iOS — объем кода уменьшится в несколько раз.



Надеемся, что материал был для вас полезен, команда MSLibrary for iOS

Другие статьи:
Захват и верификация телефонных номеров с помощью регулярных выражений, для iOS и не только… Часть 1
Захват и верификация телефонных номеров с помощью регулярных выражений, для iOS и не только… Часть 2
Реализация множественного выбора условий с помощью битовых масок, для iOS и не только…
ПРОСТО: удаляем из строки ненужные символы, используя регулярные выражения, для iOS и не только…
Создание и компиляция кроссплатформенных (универсальных) библиотек в Xcode
Tags:
Hubs:
-4
Comments 7
Comments Comments 7

Articles