51

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

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

@interface MyClass : NSObject {
    CGFloat weight;
}

@property、@ synthesizeはなく、上記の宣言だけです。

また、Appleが_inFrontOfTheirPrivateInstanceVariablesを追加していることも知っていますが、他の人がそうしているのを見たくないと言っていました。

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

4

7 に答える 7

60

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

このAppleのドキュメントには、可変スコープと可視性に関する詳細が記載されています。

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

変数の前の先頭の_に関しては、Appleもこのプレフィックスを「プライベート」メソッド用に予約していることに注意してください。問題を回避するための最良の方法は、独自の変数とメソッドに通常の命名規則を使用することです。ただし、Cocoa(NSObject以外)から何かをサブクラス化しない限り、問題が発生しないことをかなり確信で​​きます。

于 2009-08-11T19:41:53.353 に答える
31

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

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

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

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

于 2011-06-09T15:00:11.110 に答える
9

プライベートメソッドを定義するには、@ 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:は引き続きメソッドを呼び出すことに注意してください。ivarsは完全にプライベートになります。

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

于 2012-08-19T19:27:43.143 に答える
3

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

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

于 2009-08-11T19:45:39.713 に答える
2

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

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

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

于 2009-08-11T20:49:58.867 に答える
2

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

.mファイル内

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

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

于 2013-03-05T18:26:17.490 に答える
1

実際のプライベートインスタンス変数を作成することはできません。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
于 2013-09-06T09:30:29.497 に答える