在iOS应用程序中存储全局常量的位置?

时间:2011-08-19 01:59:23

标签: ios objective-c cocoa-touch constants global

我的iOS应用中的大多数模型都在查询网络服务器。我想有一个配置文件存储服务器的基本URL。它看起来像这样:

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

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

通过注释掉一行或另一行,我可以立即更改模型指向的服务器。我的问题是,在iOS中存储全局常量的最佳实践是什么?在Android编程中,我们有这个内置的strings resource file。在任何Activity(相当于UIViewController)中,我们可以通过以下方式检索这些字符串常量:

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

我想知道iOS SDK是否具有存储常量的类似位置。如果没有,Objective-C中的最佳做法是什么?

11 个答案:

答案 0 :(得分:167)

嗯,你想要与它相关的接口本地声明 - 应用程序范围的常量文件不是一件好事。

同样,最好只声明一个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

除了省略C ++兼容的Extern声明之外,这是您在Apple的Obj-C框架中通常会看到的。

如果常量只需要对一个文件或函数可见,那么static NSString* const baseUrl中的*.m就可以了。

答案 1 :(得分:145)

你也可以做一个

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

在“常量”头文件中,例如constants.h。然后做

#include "constants.h"

位于您需要此常量的每个文件的顶部。

这样,您可以根据编译器标志在服务器之间切换,如:

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

答案 2 :(得分:39)

我定义全局常量的方式:


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。

答案 3 :(得分:5)

您还可以像这样连接字符串常量:

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

答案 4 :(得分:3)

  1. 我在YOURPROJECT-Prefix.pch文件中定义全局常量。
  2. #define BASEURl @"http://myWebService.appspot.com/xyz/xx"
  3. 然后项目中的任何地方使用BASEURL:

    NSString *LOGIN_URL= [BASEURl stringByAppendingString:@"/users/login"];
    
  4. 更新: 在Xcode 6中,您将找不到项目中创建的默认.pch文件。因此,请使用PCH File in Xcode 6在项目中插入.pch文件。

    更新: 对于SWIFT

    1. 创建新的Swift文件[空无课]说[AppGlobalMemebers]
    2. &安培;马上声明/定义成员

      示例:

      var STATUS_BAR_GREEN : UIColor  = UIColor(red: 106/255.0, green: 161/255.0, blue: 7/255.0, alpha: 1)  //
      
      1. 如果要在任何类文件中定义应用程序全局成员,请说Appdelegate或Singleton类或任何类,在类定义上面声明给定成员

答案 5 :(得分:3)

我认为另一种方法更简单,你只需将它包含在你需要它们的文件中,而不是所有文件中,例如.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"

答案 6 :(得分:2)

全局声明很有意思,但对我来说,改变代码的方式是拥有类的全局实例。我花了几天时间才真正了解如何使用它,所以我在这里快速总结了它

我使用全局类实例(每个项目1或2,如果需要),重新组合核心数据访问或某些交易逻辑。

例如,如果您想要一个处理所有餐馆餐桌的中心对象,您可以在启动时创建对象,就是这样。如果您不需要保存数据库,则可以处理数据库访问或在内存中处理它。它是集中的,你只展示有用的界面......!

这是一个很好的帮助,面向对象,是一种让你在同一个地方获得所有东西的好方法

几行代码:

@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]

答案 7 :(得分:0)

我之前使用过的方法是创建文件Settings.plist并在使用NSUserDefaults启动时将其加载到registerDefaults:。然后,您可以使用以下内容访问其内容:

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

虽然我没有进行任何Android开发,但听起来好像这与您描述的字符串资源文件类似。唯一的缺点是您无法使用预处理器在设置之间进行切换(例如,在DEBUG模式下)。我想你可以加载一个不同的文件。

NSUserDefaults documentation.

答案 8 :(得分:0)

对于一个号码,您可以像

一样使用它
#define MAX_HEIGHT 12.5

答案 9 :(得分:0)

接受的答案有两个缺点。 首先,正如其他人所指出的那样,#define的使用更难以调试,而是使用extern NSString* const kBaseUrl结构。 其次,它为常量定义了一个文件。 IMO,这是错误的,因为大多数类都不需要访问这些常量或访问所有这些常量,如果在那里声明所有常量,文件会变得臃肿。更好的解决方案是在3个不同的层上模块化常数:

  1. 系统层:SystemConstants.hAppConstants.h,描述全局范围内的常量,可由系统中的任何类访问。这里只声明那些必须从不相关的不同类访问的常量。

  2. 模块/子系统层:ModuleNameConstants.h,描述一组常量,这些常量对于模块/子系统内的一组相关类是典型的。

  3. 类层:常量驻留在类中,仅由它使用。

  4. 只有1,2与问题有关。

答案 10 :(得分:-1)

使用从plist初始化的配置对象。 为什么要用其他不相关的外部东西来打扰其他类?

出于这个原因,我创建了eppz!settigns soley。有关合并plist的默认值,请参阅文章Advanced yet simple way to save to NSUserDefaults

enter image description here