web-dev-qa-db-ja.com

実際のプライベートインスタンス変数を作成する方法は?

外部からアクセスできないインスタンス変数を作成したい。 Objective-Cではそのようなことが可能ですか? Appleにはプライベート変数とそのようなものがありますが、人々がそれらについて知っていれば、それらを使用することができます。Apple明らかに、他の人がそこにあるものを見つければ、それらのものにアクセスできます。

今までは、このようなものがプライベートインスタンス変数を作成すると信じていました。

@interface MyClass : NSObject {
    CGFloat weight;
}

@ property、@ synthesize、上記の宣言はありません。

また、Appleが_inFrontOfTheirPrivateInstanceVariablesを追加しますが、他の人がそうするのを見たくないのは、それを行うときに誤って隠されたインスタンス変数をオーバーライドする可能性があるためです。

ここでのトリックは何ですか?

51
HelloMoon

@private内で{}キーワードを使用して、後続のすべての変数宣言をプライベートにすることができます。デフォルトの可視性は@protected(Javaのprotectedに似ています)であり、通常はうまく機能します。クラスの外部から直接アクセスできるようにするには、変数を@publicとして明示的に宣言する必要があります。

This Apple documentation には、変数のスコープと可視性に関する詳細があります。

「プライベートAPI」とプライベート変数にも違いがあります。 Objective-Cでは、メソッドをプライベートにすることはできません。誰でもメソッドを呼び出すことができます。 「秘密の」メソッドを作成する方法はいくつかありますが、それはこの質問の範囲外です。関連するSOの質問:

変数の前にある先頭の_に関しては、Appleも「プライベート」メソッド用にこのプレフィックスを予約しています。問題を回避するための最善の方法は、通常の命名規則を使用することですNS.

60
Quinn Taylor

XCode 4以降で利用可能な新しいLLVMコンパイラを使用すると、@private実装(.m)ファイル内のデフォルトカテゴリの変数:

@interface ClassName()
{
@private
// private variables here
}
@end

@implementation ClassName
// you can use private variables here
@end

私は、プライベート変数がヘッダーファイルにもたらす汚染を嫌うので、これが便利だと感じています。

31

@interfaceではなく@implementationのみでプライベートメソッドを使用することで、プライベートメソッドを定義できます。

同様に、@ interface内のパブリックivarの場合と同様に、@ implementationの開始時に匿名ブロック内でプライベートインスタンス変数を定義できます。

次の例を参照してください。

@interface EXClass : NSObject
{
uint8_t publicInteger;
float publicFloat;
}

-(void)publicMethod;
@end

@implementation EXClass
{
uint8_t privateInteger;
float privatefloat;
}

-(BOOL)privateMethod {
return FALSE;
}

ただし、Objective-Cメソッドは(C++のコンパイル時バインディングではなく)実行時にメッセージとして送信されるため、respondsToSelector:は引き続きtrueを返し、performSelector:はメソッドを呼び出します。 ivarは完全にプライベートです。

ただし、ライブラリを作成する場合、理論的には、ヘッダーファイルで宣言しなかったメソッドについてだれも知りません。

9
stef

Objective-CのすべてのiVarはデフォルトで保護されています。アクセサメソッドを記述しない場合、他のクラスは変数を見ることができません。

2つの例外は、カテゴリとサブクラスです。

3
kubi

Appleのサンプルアプリ(PaintGL)で次の使用法を見ました

.mファイル内

@interface MyClass (private)
  - (void) privateMethod();
  @property(...) myProperty;
@end

免責事項:サンプルアプリにはメソッド宣言しかありません。プライベートプロパティの宣言を見ました in SO thread

2
Ege Akpinar

Appleインスタンス変数の名前付けに関するドキュメントは、プライベートメソッドドキュメントのようにインスタンス変数の名前にアンダースコアを使用することを明示的に警告しません。

インスタンス変数とデータ型の命名

また、Wil Shipleyと他のいくつかのOS X開発者とのアンダースコアに関する会話も覚えています。 Obj-Cコンパイラの動作方法のため、Appleがフレームワークのクラスに新しいインスタンス変数を追加する場合、それらのフレームワークを使用するすべてのアプリを再コンパイルする必要があります。既存のインスタンス変数に関しては、1つを踏むと警告が表示されます。

2
criscokid

notは、実際のプライベートインスタンス変数を作成できます。 Objective-Cは動的言語であるため、任意の変数(@privateを含む)にアクセスできます。

私の最善のアプローチ:

.mファイルの実装ブロックで使用します。その後、それは表示されず、KVCをブロックするため、KVCは機能しません

@implementation ClassName {
    // default to @protected
    // but the subclasses can't see ivars created in the implementation block
    float number;
}

+ (BOOL)accessInstanceVariablesDirectly {
    return NO; // no KVC
}

@end
1
Binarian