Ld: дублирующий символ - вызванный константой

Я определял NSString для использования в качестве домена ошибки в NSError и копировал, как это делает ASIHttpRequest.

NSString* const FPServerAPIErrorDomain = @"FPServerAPIErrorDomain";

Я помещаю const в свой собственный .h файл   //FPServerAPICoordinatorConstants.h

#ifndef FirePlayer_FPServerAPICoordinatorConstants_h
#define FirePlayer_FPServerAPICoordinatorConstants_h

NSString* const FPServerAPIErrorDomain = @"FPServerAPIErrorDomain";

#endif

но когда я включил его в более чем один .m

SomeFile.m

#import "FPServerAPICoordinatorConstants.h"

SomeOtherFile.m

#import "FPServerAPICoordinatorConstants.h"

У меня есть ошибка компоновщика 'дубликат символа'

ld: duplicate symbol _FPServerAPIErrorDomain in SomeFile.o and ....SomeOtherFile.o for architecture armv7

поэтому я изменяю const на #define, и он работает нормально.

//  FPServerAPICoordinatorConstants.h

#ifndef FirePlayer_FPServerAPICoordinatorConstants_h
#define FirePlayer_FPServerAPICoordinatorConstants_h


//THIS WAS TRIGGERING link errors
//NSString* const FPServerAPIErrorDomain = @"FPServerAPIErrorDomain";
//working OK
#define FPServerAPIErrorDomain @"FPServerAPIErrorDomain"

#endif

Но есть ли способ заставить const в глобальном пространстве не "дублировать символ"?

Ответы

Ответ 1

В вашем файле заголовка вы хотите:

extern NSString *const FPServerAPIErrorDomain;

а затем в файле реализации (возможно, вам понадобится FPServerAPICoordinatorConstants.m):

NSString *const FPServerAPIErrorDomain = @"FPServerAPIErrorDomain";

Затем вы можете импортировать заголовок в несколько файлов и не получать повторяющиеся ошибки символов.

[Кстати, вам не нужны защитники #ifndef, если вы используете #import.]

Ответ 2

Невозможно создать одну и ту же (глобальную) переменную дважды в том же пространстве имен (без получения ошибки).

Ответ 3

Каждый символ должен быть определен только один раз; то есть он должен быть определен только в одном файле m. Поместив определение в файл заголовка, он определяется в каждом файле m, который включает этот заголовок.

Определите его в одном из ваших файлов m (в зависимости от того, что наиболее важно) и измените то, что у вас есть в заголовке, на объявление (используя ключевое слово extern).

Определение содержит пространство для данных; объявление просто сообщает компилятору, что есть определение где-то еще. Поэтому каждый m файл, который использует константу, должен иметь объявление, но только один файл m должен иметь определение.