web-dev-qa-db-ja.com

iPhoneのObjective Cの静的文字列変数

IPhone(Objective C)で静的文字列を作成してアクセスする方法クラスAでstatic NSString *str = @"OldValue"を宣言します。

クラスBでこれに値をstr = @"NewValue"として割り当てます。この値は、クラスBのすべてのメソッドで保持されます。ただし、クラスBでアクセスすると(Bでの割り当て後)、OldValueとして取得されます。何か不足していますか?他のクラスでexternを使用する必要がありますか?

よろしくお願いします、Yogini

26
Yogini

Update:Xcode 8以降、Objective-C doesにはクラスプロパティがあります。注意してください、それは主に構文上の砂糖です。これらのプロパティは自動合成されないため、実装は基本的に以前と同じです。

// MyClass.h
@interface MyClass : NSObject
@property( class, copy ) NSString* str;
@end

// MyClass.m
#import "MyClass.h"

@implementation MyClass

static NSString* str;

+ (NSString*) str 
{
    return str;
}

+ (void) setStr:(NSString*)newStr 
{
    if( str != newStr ) {
        str = [newStr copy];
    }
}
@end


// Client code
MyClass.str = @"Some String";
NSLog( @"%@", MyClass.str ); // "Some String"

WWDC 2016 What's New in LLVM を参照してください。クラスプロパティ部分は、5分の前後から始まります。

元の回答:

Objective-Cにはクラス変数がありません。これは、あなたが探していると思います。あなたがしているように、あなたは静的変数でそれをちょっと偽ることができます。

静的なNSStringをクラスの実装ファイルに入れて、それにアクセス/変更するクラスメソッドを提供することをお勧めします。このようなもの:

// MyClass.h
@interface MyClass : NSObject {
}
+ (NSString*)str;
+ (void)setStr:(NSString*)newStr;
@end

// MyClass.m
#import "MyClass.h"

static NSString* str;

@implementation MyClass

+ (NSString*)str {
    return str;
}

+ (void)setStr:(NSString*)newStr {
    if (str != newStr) {
        [str release];
        str = [newStr copy];
    }
}
@end
44
zpasternack

静的変数がクラスのすべてのインスタンスにスコープされるJavaとは異なり、Cのstaticは、変数が宣言されているファイル内からのみ変数にアクセスできることを意味します。これにより、関数内で静的変数を宣言するなどの操作を行うことができます。これにより、最初に値を設定するだけです このような .

クラスA、B、Cの関係については、言及しなかった1つがあります。それらが継承階層にあり、Javaのように静的変数が継承されることを期待している場合、zpasternackが機能します。

3つのクラスが無関係で、Aで宣言された値にアクセスするだけの場合は、externがより適切な方法です。この場合、変数をClassA.hでexternとして宣言し、それをClass.mで定義します。 ClassBおよびClassCがClassA.hをインポートする限り、それらは同じextern定義に対してリンクできます。

1つの細かい点は、externを単独で使用する代わりに、objc-api.hで定義され、C++でのコンパイルも処理するOBJC_EXPORTを使用する方がより堅牢であることです。ここにコードサンプルがあります:

// ClassA.h
OBJC_EXPORT NSString* commonString;
...

// ClassA.m
NSString* commonString = @"OldValue";

// ClassB.m
#import "ClassA.h"
...
commonString = @"NewValue"; // Can be inside a function or method

もちろん、この方法で外部変数を使用すると、悪名高い悪名高いグローバル変数が作成されます。これは、だれでも読み取りまたは書き込みができるという点で脆弱です。アクセスは制御されていません。これは単純なアプローチであり、staticexternの使用についての質問に答えます。ただし、設計原則として、変数をクラスメソッドでラップすることによって提供されるカプセル化は、より複雑ですが、はるかに安全です。オブジェクト指向言語では、達成しようとしている効果がクラス静的メソッドの効果である場合、カプセル化はおそらく正しい方法です。

30
Quinn Taylor