Где хранить глобальные константы в приложении iOS?

Большинство моделей в моем приложении для iOS запрашивают веб-сервер. Я хотел бы иметь файл конфигурации, хранящий базовый URL-адрес сервера. Это будет выглядеть примерно так:

// production
// static NSString* const baseUrl = "http://website.com/"

// testing
static NSString* const baseUrl = "http://192.168.0.123/"

Комментируя одну или другую строку, я могу мгновенно изменить сервер, на который указывают мои модели. У меня такой вопрос, какова лучшая практика для хранения глобальных констант в iOS? В программировании Android у нас есть этот файл ресурсов встроенных строк. В любой деятельности (эквивалент в UIViewController), мы можем получить эти строковые константы с:

String string = this.getString(R.string.someConstant);

Мне было интересно, есть ли в iOS SDK аналогичное место для хранения констант. Если нет, то как лучше всего это делать в Objective-C?

Ответ 1

Вы также можете сделать

#define kBaseURL @"http://192.168.0.123/"

в заголовочном файле "константы", скажем constants.h. Тогда do

#include "constants.h"

в верхней части каждого файла, где вам нужна эта константа.

Таким образом, вы можете переключаться между серверами в зависимости от флагов компилятора, например:

#ifdef DEBUG
    #define kBaseURL @"http://192.168.0.123/"
#else
    #define kBaseURL @"http://myproductionserver.com/"
#endif

Ответ 2

Ну, вы хотите, чтобы объявление было локальным для интерфейсов, к которым он относится, - файл констант в приложении - это не очень хорошо.

Кроме того, желательно просто объявить символ extern NSString* const, а не использовать #define:


SomeFile.h

extern NSString* const MONAppsBaseUrl;

SomeFile.m

#import "SomeFile.h"

#ifdef DEBUG
NSString* const MONAppsBaseUrl = @"http://192.168.0.123/";
#else
NSString* const MONAppsBaseUrl = @"http://website.com/";
#endif

Помимо пропусков декларации Extern, совместимой с С++, это то, что вы обычно увидите в инфраструктурах Apple Obj-C.

Если константа должна быть видна только одному файлу или функции, то static NSString* const baseUrl в вашем *.m хороша.

Ответ 3

Способ определения глобальных констант:


AppConstants.h

extern NSString* const kAppBaseURL;

AppConstants.m

#import "AppConstants.h"

#ifdef DEBUG
NSString* const kAppBaseURL = @"http://192.168.0.123/";
#else
NSString* const kAppBaseURL = @"http://website.com/";
#endif

Затем в файле {$ APP} -Prefix.pch:

#ifdef __OBJC__
  #import <UIKit/UIKit.h>
  #import <Foundation/Foundation.h>
  #import "AppConstants.h"
#endif

Если у вас возникли какие-либо проблемы, сначала убедитесь, что у параметра Precompile Prefix Header установлено значение NO.

Ответ 4

Вы также можете объединить строковые константы следующим образом:

  #define kBaseURL @"http://myServer.com"
  #define kFullURL kBaseURL @"/api/request"

Ответ 5

  • Я определяю глобальную константу в файле YOURPROJECT-Prefix.pch.
  • #define BASEURl @"http://myWebService.appspot.com/xyz/xx"
  • тогда где-нибудь в проекте используется BASEURL:

    NSString *LOGIN_URL= [BASEURl stringByAppendingString:@"/users/login"];
    

Обновлено: В Xcode 6 вы не найдете файл .pch по умолчанию, созданный в вашем проекте. Поэтому, пожалуйста, используйте PCH файл в Xcode 6, чтобы вставить файл .pch в свой проект.

Обновление: Для SWIFT

  • Создать новый файл Swift [empty without class] сказать [AppGlobalMemebers]
  • & Сразу объявите/определите участника

    Пример:

    var STATUS_BAR_GREEN : UIColor  = UIColor(red: 106/255.0, green: 161/255.0, blue: 7/255.0, alpha: 1)  //
    
    1. Если вы хотите определить глобальный член приложения в любом файле класса, скажем, Appdelegate или Singleton class или any, объявите данный член выше определения класса

Ответ 6

Я думаю, что другой способ сделать это намного проще, и вы просто включите его в нужные вам файлы, а не ВСЕ файлы, например, с префиксным файлом .pch:

#ifndef Constants_h
#define Constants_h

//Some constants
static int const ZERO = 0;
static int const ONE = 1;
static int const TWO = 2;

#endif /* Constants_h */

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

#include "Constants.h"

Ответ 7

Глобальные декларации интересны, но для меня, что сильно изменилось, мой путь к коду состоял в том, чтобы иметь глобальные экземпляры классов. Мне понадобилось пару дней, чтобы по-настоящему понять, как с этим работать, поэтому я быстро обобщил его здесь.

Я использую глобальные экземпляры классов (1 или 2 для каждого проекта, если необходимо), для перегруппировки доступа к основным данным или к какой-либо торговой логике.

Например, если вы хотите, чтобы центральный объект обрабатывал все таблицы ресторанов, вы создаете объект при запуске, и это все. Этот объект может обрабатывать обращения к базам данных OR или обрабатывать его в памяти, если вам не нужно его сохранять. Он централизован, вы показываете только полезные интерфейсы...!

Это отличная помощь, объектно-ориентированная и хороший способ получить все, что вы делаете в одном и том же месте.

Несколько строк кода:

@interface RestaurantManager : NSObject
    +(id) sharedInstance;
    -(void)registerForTable:(NSNumber *)tableId;
@end 

и реализация объекта:

@implementation RestaurantManager

+ (id) sharedInstance {
    static dispatch_once_t onceQueue;

    dispatch_once(&onceQueue, ^{
        sharedInstance = [[self alloc] init];
        NSLog(@"*** Shared instance initialisation ***");
    });
    return sharedInstance;
}

-(void)registerForTable:(NSNumber *)tableId {
}
@end

для его использования это действительно просто:

[[RestaurantManager sharedInstance] registerForTable: [NsNumber numberWithInt: 10]]

Ответ 8

Подход, который я использовал ранее, - это создать файл Settings.plist и загрузить его в NSUserDefaults при запуске с помощью registerDefaults:. Затем вы можете получить доступ к его содержимому:

// Assuming you've defined some constant kMySettingKey.
[[NSUserDefaults standardUserDefaults] objectForKey:kMySettingKey];

Пока я не делал никаких разработок на Android, звучит так, как будто это аналогично файлу ресурсов строк, который вы описали. Единственным недостатком является то, что вы не можете использовать препроцессор для обмена между настройками (например, в режиме DEBUG). Я полагаю, вы могли бы загружать в другой файл.

NSUserDefaults документация.

Ответ 9

Для номера вы можете использовать его как

#define MAX_HEIGHT 12.5

Ответ 10

Я бы использовал объект конфигурации, который инициализируется с помощью plist. Зачем беспокоиться о других классах с нерелевантными внешними материалами?

Я создал eppz!settigns soley по этой причине. См. Статью Расширенный, но простой способ сохранить NSUserDefaults для включения значений по умолчанию из plist.

enter image description here

Ответ 11

Принятый ответ имеет 2 недостатка. Во-первых, как указывалось другими, использование #define, которое сложнее отлаживать, использует вместо него структуру extern NSString* const kBaseUrl. Во-вторых, он определяет один файл для констант. IMO, это неправильно, потому что большинство классов не нуждаются в доступе к этим константам или для доступа ко всем из них, плюс файл может раздуваться, если все константы объявлены там. Лучшим решением будет модуляция констант в 3 разных слоях:

  • Системный уровень: SystemConstants.h или AppConstants.h, который описывает константы в глобальной области видимости, к которым может обращаться любой класс в системе. Объявите здесь только те константы, к которым необходимо получить доступ из разных классов, которые не связаны.

  • Уровень модуля/подсистемы: ModuleNameConstants.h, описывает набор констант, типичных для набора связанных классов, внутри модуля/подсистемы.

  • Класс: Константы находятся в классе и используются только им.

Только 1,2 связаны с вопросом.