Глобальные константы в Objective-C

#iphone #objective-c #ios5 #global-variables

#iPhone #objective-c #ios5 #глобальные переменные

Вопрос:

У меня есть файл под названием Constants.h:

 extern NSString * const BASE_URL;
  

и Constants.m:

 #ifdef DEBUG
    NSString * const BASE_URL = @"http://www.example.org ";
#else
    NSString * const BASE_URL = @"http://localhost";
#endif
  

Первый вопрос: как я могу переключить DEBUG на быть True и False ?


У меня есть файл контроллера просмотра MyViewController.m :

 #import "MyViewController.h"
#import "Constants.h"

// this doesn't works. see above for the error.
static NSString * const ANOTHER_URL = [NSString stringWithFormat:@"%@%@", BASE_URL, @"/path/"];

@implementation HomeViewController

[...]
  

Код не работает и возвращает мне эту ошибку:

 error: Semantic Issue: Initializer element is not a compile-time constant
  

Как я могу это исправить?

Мне нужно объединить несколько глобальных переменных строк с другими строками для создания различных URL-адресов.


ОБНОВЛЕНИЕ 1

Теперь Constants.m это:

 #import "Constants.h"

#ifdef DEBUG
    #define DEF_BASE_URL "http://www.example.org/"
#else
    #define DEF_BASE_URL "http://localhost/"
#endif

NSString * const BASE_URL = (NSString*)CFSTR(DEF_BASE_URL);
NSString * const API_URL = (NSString*)CFSTR(DEF_BASE_URL "api/");
NSString * const API_SETTINGS_URL = (NSString*)CFSTR(API_URL "settings/");
  

Но в последней строке есть ошибка Ошибка синтаксического анализа: ожидаемая ‘)’.
Вероятно, я могу использовать CFSTR только с макросами. Мне нужно найти способ иметь все мои глобальные переменные.

Комментарии:

1. В Xcode в свойствах проекта (я забыл точные термины, и у меня нет под рукой среды Xcode) укажите свой переключатель ОТЛАДКИ в «макросы препроцессора C» или что-то в этом роде. Я считаю, что вам нужно добавить к переключателю префикс -D, например: -DDEBUG. Но я бы предложил использовать имя переключателя, отличное от «DEBUG» — что-то вроде «MY_DEBUG_MODE» — чтобы вы не рисковали столкнуться с «DEBUG» в другом месте…. Ах, вот это в некоторых деталях.

Ответ №1:

Решение A:

Лично я бы просто использовал функцию для ANOTHER_URL .

Решение B:

Если вам действительно нужна константа: вы должны иметь возможность использовать правила конкатенации cstring через #define , затем передать это через CFSTR() :

 // defs.h
extern NSString * const BASE_URL;
extern NSString * const ANOTHER_URL;

// defs.m

#ifdef DEBUG
#define DEF_BASE_URL "http://www.example.org"
#else
#define DEF_BASE_URL "http://localhost"
#endif

NSString * const BASE_URL = (NSString*)CFSTR(DEF_BASE_URL);
NSString * const ANOTHER_URL = (NSString*)CFSTR(DEF_BASE_URL "/path/");
  

Решение C:

Если вы хотите создать только одну с помощью инициализации, вы также можете создать локальную статическую функцию / метод в переводах C / ObjC (затем при необходимости используйте C или ObjC visibility):

 NSString * URL() {
  static NSString * const ANOTHER_URL = [NSString stringWithFormat:@"%@%@", BASE_URL, @"/path/"];
  return ANOTHER_URL;
}
  

Комментарии:

1. Спасибо, чувак. Но у меня проблема. Если я помещу NSString * const ANOTHER_URL = (NSString*)CFSTR(DEF_BASE_URL "/path/"); в MyViewController.m перед @implementation , это вернет мне ошибку: Parse error: Expected ) . Я уверен, что код написан нормально. Возможно, я не могу использовать это в viewcontrollers? Почему? В Constants.m работает хорошо, без ошибок.

2. Ошибка копирования / вставки @Fred — после DEF_BASE_URL значения s была точка с запятой в конце.

3. @Fred трюк действителен для строк c, но не для CF / NSStrings. таким образом, вы можете создавать / составлять их, используя строки c, а затем отправлять результат через CFSTR — но он не может принимать форму типа: cstring_literal NSString для создания литерала CF / NSString. поэтому просто создайте их, используя строки c.

4. Как? И, по вашему мнению, это лучший способ сделать это? Если вы хорошо поняли, чего я пытаюсь достичь, у меня есть BASE_URL и для каждого контроллера представления у меня есть несколько URL-адресов, составленных из BASE_URL и других строк.

5. вы также можете создать их так, чтобы они расширялись следующим образом: static NSString* const AAA = @"A""A""A";

Ответ №2:

Во-первых, вы можете указать Xcode установить некоторые макросы препроцессора для отладочных сборок. Используйте опцию сборки «макросы препроцессора».

Что касается вашего второго вопроса, вы не можете вызвать метод objective-C для заполнения константы, потому что этот материал недоступен во время компиляции. Ваш лучший вариант — определить глобальную переменную, а затем присвоить ей значение в методе класса ‘initialize’.

 static NSString * ANOTHER_URL;

  initialize {
    ANOTHER_URL = [NSString stringWithFormat:@"%@%@", BASE_URL, @"/path/"];
}
  

инициализация вызывается перед созданием вашего первого экземпляра класса, поэтому это безопасно. Вам придется отказаться от ключевого слова const, но я уверен, что вы можете доверять себе! 😉

Ответ №3:

#определите DEBUG 1 или 0 для отключения.

Ошибка заключается в том, что вы вызываете метод NSString, в то время как его константа компиляции. Другими словами, вы сообщаете компилятору то, с чем он просто не может справиться. Вам нужно будет инициализировать такую динамическую ссылку при запуске, компилятор не может сделать это за вас.

Комментарии:

1. вау, lol #, по-видимому, создает заголовок в сообщении SO .. извините за это. в любом случае вы всегда можете сделать что-то подобное в (void)initialize, который вызывается перед созданием вашего класса.