#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, который вызывается перед созданием вашего класса.