6

私にとって、Objective-C 開発者としての過去は単純なものでした。クラスがパブリックである必要のあるすべてのフィールドはプロパティであり、すべてのプライベート フィールドはゲッターまたはセッターのないインスタンス変数でした。しかし、実装ファイル内でプライベート インターフェイスを使用してプライベート プロパティを宣言する人をよく見かけます。そして、それが今のやり方だと言われました。

これはうまく機能しますが、利点を理解するのは難しいです。ゲッターまたはセッターに何らかのロジックが必要ない限り、公開されていないすべてのものにインスタンス変数を使用し続けます。プロパティの使用を認めてから、キーワード self を使用すると、コードが少し読みやすくなります。プロパティがクラスに属しているかどうか、またはメソッド内の単なるローカル変数であるかどうかを確認できますが、それだけが理由ではありません。

私有財産を使用しない理由は何ですか?

4

7 に答える 7

7

ivar よりも (プライベート) プロパティを使用する理由はいくつかあります。

  • あなたが言ったように、プロパティを使用すると、変数にアクセスするだけでなく、追加のコーディングを行うアクセサ メソッドを簡単に使用できます。
  • KVOは ivar では機能しません。
  • パブリック読み取り専用プロパティを実装専用の読み取り書き込みにして、ゲッターに加えてセッターを合成します(ブラッドが指摘したように)
  • 個人的な好み、慣れまたは怠惰 (プロパティはパブリックでしたが、プライベートに変更されました)。
于 2013-11-14T16:24:44.437 に答える
1

まず、プライベート プロパティが必要ない場合は、プロパティを使用しないでください。NSString割り当て時にコピーを強制するなど、コンパイラから特定の動作を宣言的に取得したい場合を除き、プロパティを使用する利点はありません。

selfさらに、これらのプロパティにアクセスするために必ずしも を使用する必要はありません。プロパティが合成されると、自動的にまたは@synthesizeキーワードを使用して、プロパティを「バックアップ」する変数が取得されます。その変数を割り当てることは、たとえば読み取り専用として表示する場合など、プロパティにアクセスするための完全に合法的な方法です。

ただし、これらの変数を非公開にすること、つまり次のようにクラス拡張で宣言することには利点があります。

@interface MyClass() { // <<== Note the () -- it's a class extension
   SomeOtherClass *privateIvar;
}

クラス拡張 (ヘッダーの代わりに .m ファイルに入る) で変数を宣言すると、 のヘッダーを非表示にすることができます"SomeOtherClass"。これは、単一のアプリを開発するときにはほとんど重要ではありませんが、開始時には非常に役立ちます。独自のクラス ライブラリを使用した開発。

于 2013-11-14T16:25:32.200 に答える
1

IMO OPは、一部のivarをインターフェイスに、一部を実装に配置する理由を尋ねています。副次的な問題は、プロパティの理由です。

  1. ポイントはカプセル化です。パブリック インターフェイス (.h) ファイルには、クラス外の設計で使用することを意図したものだけを入れてください。実装 (.m) ファイル内の実装でのみ使用されるように設計されているものを配置します。これは公開されていないもので、クラスのユーザーに影響を与えることなく後で変更できます。

  2. プロパティは、関連付けられた ivar の setter/getter メソッドを提供します。現在の Objective-C コンパイラでは、ステートメントがない場合@synthesize、コンパイラはアンダースコア (_) で始まるプロパティと同じ名前の ivar を自動生成します。ゲッター/セッターは KVO もサポートしているため、使用状況によってはプラスになる場合があります。インターフェイス ファイルで読み取り専用のプロパティを宣言し、実装ファイルのクラス拡張で readwrite を宣言することは可能であることに注意してください。

そのため、現在のベスト プラクティスは、すべての ivar にプロパティを使用し、プロパティ ステートメントを、パブリックに設計されている場合はインターフェイス ファイルに配置し、プライベートに設計されている場合はクラス拡張の実装ファイルに配置することです。これにより、パブリック メソッドとプロパティのみを公開するクリーンなインターフェイス ファイルが提供されました。

于 2013-11-14T16:47:18.303 に答える
0

さまざまなレベルのプライベート性を持つことができるのは、カプセル化の問題です...

もともと Objective-C では、ランタイムは実行時に実際のフィールドをオブジェクトに追加することをサポートしていなかったため、すべての iVar をクラスにリストする必要がありました。

@interface MyClass : NSObject
{
//every ivar that MyClass adds to NSObject must be here
}

これは、しばらくの間、シンプルで十分に優れたシステムでした...

プライベートな iVar でさえ宣言する必要がありましたが、コンパイラは間違ったスコープでそれらにアクセスすることを許可しませんでした。

@interface MyClass : NSObject
{
 @private
 id someObj;
}

この可視性指定子は、次のようなアクセスを制限しました:

//someotherclass.m

 + (void)doSomething
 {
     MyCLass * mc = [MyClass new];
     mc->someObj = [SomeOtherClass new]; // error cant access private variable...
 }

しかし、ポインタ算術でそれに到達する可能性があるため、難読化するために、クラスで次のようなものが表示されます。

@interface MyClass : NSObject
{
 @private
 void * __reserved1;
 void * __private1;
}

それはかなり良い難読化です...

しかし、待ってください....もっと良い方法があるはずです!

壊れにくいABIに入る

現在、クラスはスーパークラスとパブリック インターフェイスをエクスポートするだけで済みます。

@interface MyClass : NSObject
@property (readonly,retain) id someIVar;

クラスの内容の残りの部分は、クラス拡張に含めることができます。

@interface MyClass ()
{
 id someObj;
}
@property (readwrite,retain) id someIVar;

これはiPhoneと64ビットOS Xでのみ機能することに注意してください.32ビットOS Xはまだ古いABIであり、そこで機能する必要があるライブラリは古い方法である必要があります.

于 2013-11-14T16:32:30.683 に答える
0

プロパティを適切に使用すると、より「便利」になる可能性があります (少なくとも、KVO 対応プロパティの場合に willChange / didChange の呼び出しを忘れることを心配する必要がないため)。そのため、1 秒あたりのフレーム数を本当に気にしない限り、プロパティを使用することをお勧めします。その場合は、この素晴らしい投稿をチェックしてください。

于 2013-11-14T16:34:09.553 に答える
0

object-c のプロパティは単なるインスタンス変数ではありません。これらは、インスタンス変数に基づく getter メソッドと setter メソッドの組み合わせです。

通常、実装ファイル (プライベート クラス拡張) にプロパティを追加するときは、公開readonlyプロパティをreadwriteプロパティにして、キー値コーディングなどのすべてのプロパティ セマンティクスを設定して保持できるようにします。プロパティはコピー保持も処理します。

これは、パブリック インターフェイスを実装から分離しておく方法にすぎません。

于 2013-11-14T16:24:12.193 に答える
-1

それは本当に簡単です。

private を使用する場合は、次の@propertyプロパティを .m 内に追加します。

@interface MyViewController ()

@property (nonatomic, strong) NSString *myPrivateStringProperty;

@end

@implementation MyViewController

@end

ここでは、プロパティは .m でのみアクセスできます。

public を使用する場合は、次の@propertyプロパティを .h 内に追加します。

@interface MyViewController : UIViewController

@property (nonatomic, strong) NSString *myPublicStringProperty;

@end

ここでは、プロパティはクラスの外からアクセスできます。

于 2013-11-14T16:28:14.173 に答える