私はCocoaNSString
アプリケーションを開発しており、好みのキー名を保存する方法として定数sを使用しています。
必要に応じてキーを簡単に変更できるので、これは良い考えだと思います。
さらに、それは「ロジックからデータを分離する」という概念全体です。
とにかく、これらの定数をアプリケーション全体に対して一度定義する良い方法はありますか?
簡単でインテリジェントな方法があると確信していますが、今のところ、私のクラスは使用するクラスを再定義するだけです。
次のようなヘッダーファイルを作成する必要があります。
// Constants.h
FOUNDATION_EXPORT NSString *const MyFirstConstant;
FOUNDATION_EXPORT NSString *const MySecondConstant;
//etc.
(コードが混合C / C ++環境または他のプラットフォームで使用されない場合のextern
代わりに使用できます。)FOUNDATION_EXPORT
このファイルは、定数を使用する各ファイル、またはプロジェクトのプリコンパイル済みヘッダーに含めることができます。
これらの定数は、次の.m
ようなファイルで定義します。
// Constants.m
NSString *const MyFirstConstant = @"FirstConstant";
NSString *const MySecondConstant = @"SecondConstant";
Constants.m
アプリケーション/フレームワークのターゲットに追加して、最終製品にリンクする必要があります。
'd定数の代わりに文字列定数を使用する利点は、文字列比較()よりもはるかに高速なポインタ比較( )(および読みやすいIMO)#define
を使用して同等性をテストできることです。stringInstance == MyFirstConstant
[stringInstance isEqualToString:MyFirstConstant]
最も簡単な方法:
// Prefs.h
#define PREFS_MY_CONSTANT @"prefs_my_constant"
より良い方法:
// Prefs.h
extern NSString * const PREFS_MY_CONSTANT;
// Prefs.m
NSString * const PREFS_MY_CONSTANT = @"prefs_my_constant";
2 番目の利点の 1 つは、定数の値を変更してもプログラム全体が再構築されないことです。
言及することも1つあります。非グローバル定数が必要な場合は、static
キーワードを使用する必要があります。
例
// In your *.m file
static NSString * const kNSStringConst = @"const value";
static
キーワードがあるため、このconstはファイルの外部には表示されません。
@QuinnTaylorによるマイナーな修正:静的変数はコンパイルユニット内に表示されます。通常、これは(この例のように)単一の.mファイルですが、コンパイル後にリンカーエラーが発生するため、他の場所に含まれているヘッダーで宣言すると、問題が発生する可能性があります。
受け入れられた(そして正しい)答えは、「この[Constants.h]ファイルをプロジェクトのプリコンパイル済みヘッダーに含めることができる」と述べています。
初心者として、これ以上の説明なしではこれを行うのは困難でした-方法は次のとおりです: YourAppNameHere-Prefix.pch ファイル (これは Xcode のプリコンパイル済みヘッダーのデフォルト名です) で、 Constants.hをblock内#ifdef __OBJC__
にインポートします。
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "Constants.h"
#endif
また、Constants.hおよびConstants.mファイルには、受け入れられた回答に記載されているものを除いて、他に何も含めないでください。(インターフェースも実装もありません)。
私は通常、Barry Wark と Rahul Gupta によって投稿された方法を使用しています。
ただし、.h ファイルと .m ファイルの両方で同じ単語を繰り返すのは好きではありません。次の例では、行は両方のファイルでほぼ同じであることに注意してください。
// file.h
extern NSString* const MyConst;
//file.m
NSString* const MyConst = @"Lorem ipsum";
したがって、私がやりたいのは、いくつかの C プリプロセッサ機構を使用することです。例を通して説明しましょう。
マクロを定義するヘッダー ファイルがありますSTR_CONST(name, value)
。
// StringConsts.h
#ifdef SYNTHESIZE_CONSTS
# define STR_CONST(name, value) NSString* const name = @ value
#else
# define STR_CONST(name, value) extern NSString* const name
#endif
定数を定義したい .h/.m ペアでは、次のようにします。
// myfile.h
#import <StringConsts.h>
STR_CONST(MyConst, "Lorem Ipsum");
STR_CONST(MyOtherConst, "Hello world");
// myfile.m
#define SYNTHESIZE_CONSTS
#import "myfile.h"
et voila、定数に関するすべての情報は .h ファイルのみにあります。
私自身、次のような設定に使用される定数 NSStrings を宣言する専用のヘッダーがあります。
extern NSString * const PPRememberMusicList;
extern NSString * const PPLoadMusicAtListLoad;
extern NSString * const PPAfterPlayingMusic;
extern NSString * const PPGotoStartupAfterPlaying;
次に、付随する .m ファイルでそれらを宣言します。
NSString * const PPRememberMusicList = @"Remember Music List";
NSString * const PPLoadMusicAtListLoad = @"Load music when loading list";
NSString * const PPAfterPlayingMusic = @"After playing music";
NSString * const PPGotoStartupAfterPlaying = @"Go to startup pos. after playing";
このアプローチは私に役立ちました。
編集:これは、文字列が複数のファイルで使用されている場合に最適に機能することに注意してください。1 つのファイルのみがそれを使用する場合#define kNSStringConstant @"Constant NSString"
は、文字列を使用する .m ファイルで行うことができます。
// Prefs.h
extern NSString * const RAHUL;
// Prefs.m
NSString * const RAHUL = @"rahul";
Abizerが言ったように、PCHファイルに入れることができます。それほど汚れていない別の方法は、すべてのキーのインクルード ファイルを作成し、それをキーを使用しているファイルに含めるか、PCH に含めることです。それらを独自のインクルード ファイルに含めることで、これらすべての定数を探して定義する場所が少なくとも 1 か所得られます。
グローバル定数のようなものが必要な場合。pch
手っ取り早い汚い方法は、定数宣言をファイルに入れることです。
クラスメソッドを使用してみてください。
+(NSString*)theMainTitle
{
return @"Hello World";
}
たまに使います。
シングルトン クラスを使用しているので、クラスをモックし、必要に応じて定数をテスト用に変更できます。定数クラスは次のようになります。
#import <Foundation/Foundation.h>
@interface iCode_Framework : NSObject
@property (readonly, nonatomic) unsigned int iBufCapacity;
@property (readonly, nonatomic) unsigned int iPort;
@property (readonly, nonatomic) NSString * urlStr;
@end
#import "iCode_Framework.h"
static iCode_Framework * instance;
@implementation iCode_Framework
@dynamic iBufCapacity;
@dynamic iPort;
@dynamic urlStr;
- (unsigned int)iBufCapacity
{
return 1024u;
};
- (unsigned int)iPort
{
return 1978u;
};
- (NSString *)urlStr
{
return @"localhost";
};
+ (void)initialize
{
if (!instance) {
instance = [[super allocWithZone:NULL] init];
}
}
+ (id)allocWithZone:(NSZone * const)notUsed
{
return instance;
}
@end
そして、これは次のように使用されます (定数 c の短縮形の使用に注意してください - これにより、[[Constants alloc] init]
毎回入力する手間が省けます)。
#import "iCode_FrameworkTests.h"
#import "iCode_Framework.h"
static iCode_Framework * c; // Shorthand
@implementation iCode_FrameworkTests
+ (void)initialize
{
c = [[iCode_Framework alloc] init]; // Used like normal class; easy to mock!
}
- (void)testSingleton
{
STAssertNotNil(c, nil);
STAssertEqualObjects(c, [iCode_Framework alloc], nil);
STAssertEquals(c.iBufCapacity, 1024u, nil);
}
@end