5

基本的に、私は次のコードを持っています (ここで説明: Objective-C Constants in Protocol )

// MyProtocol.m
const NSString *MYPROTOCOL_SIZE;
const NSString *MYPROTOCOL_BOUNDS;

@implementation NSObject(initializeConstantVariables)

+(void) initialize {
     if (self == [NSObject class])
     {
         NSString **str = (NSString **)&MYPROTOCOL_SIZE;
         *str = [[MyClass someStringLoadedFromAFile] stringByAppendingString:@"size"];
         str = (NSString **)&MYPROTOCOL_BOUNDS;
         *str = [[MyClass someStringLoadedFromAFile] stringByAppendingString:@"bounds"];
     }
}

@end

私は疑問に思っていました: NSObject の+initializeメソッドをオーバーライドするカテゴリを持つことは安全ですか?

4

3 に答える 3

14

+initializeつまり、クラスのカテゴリにメソッドを安全に実装することはできません。既存の実装がある場合はそれを置き換えることになり、1 つのクラスの 2 つのカテゴリが両方とも を実装する+initialize場合、どちらが実行されるかは保証されません。

+loadより予測可能で明確に定義された動作がありますが、非常に多くのものが初期化されていない状態にあるため、有用なことを行うには早すぎます。

個人的には、コンパイラの注釈をスキップ+loadまたは+initialize完全に使用して、基になるバイナリ/dylib のロード時に関数を実行します。それでも、その時点で安全にできることはほとんどありません。

__attribute__((constructor))
static void MySuperEarlyInitialization() {...}

アプリケーションの起動に応じて初期化を行う方がはるかに優れています。 NSApplicationどちらも、UIApplicationアプリの起動時に少しのコードをアプリに挿入するためのデリゲート/通知フックを提供します。

于 2011-01-12T17:15:30.980 に答える
2

代わりに、クラス MyClass 内でこれら 2 つの変数をセットアップしてみませんか? また、アクセサを使用しないのはなぜですか? どこからともなく偽の定数変数を使用する代わりに、実際にそれを使用する必要があるクラスにアクセサーを定義することをお勧めします。単純な +(NSString *)myProtocolSize; プロトコルであっても、うまくいくでしょう。

また、カテゴリ内のクラスのメソッドをオーバーライドすることは「機能します」が、信頼性が低く、絶対に避ける必要があります。オーバーライドしているメソッドがカテゴリに実装されている場合、ランタイムはロード順序と実装を保証しません。追加されることはないかもしれません。

于 2011-01-12T13:40:06.443 に答える
0

タイプの変数はNSString *const、コードが実行される前に常に初期化されます。ここでは、C++ の気まぐれを無視すると仮定します。

NSString *const MY_PROTOCOL_SIZE = @"...";

タイプの変数const NSString *(アドレスではなくconst、 の内部に適用されるキーワードNSString) は、任意のコードで変更できますが、メッセージを送信することはできません。それはそれを作る目的を無効にしconstます。代わりにグローバル関数を考えてみましょう:

static NSString *GetMyProtocolSize(void) {
    return [[MyClass someStringLoadedFromAFile] ...];
}

または、クラス メソッドを使用します。

@implementation MyClass
+ (NSString *)myProtocolSize {
    return [[MyClass someStringLoadedFromAFile] ...];
}
@end

const文字列が動的な値を受け入れない理由について、以前に質問されました。これはconst、シンボルに対する影響を理解していないように見えるためです。constC のキーワードの意味をよく読んで、文字列を取得する別の方法constが適切でない場合は別の方法を検討する必要があります。

于 2011-01-12T13:17:17.940 に答える