56

Objective-C のプロパティとインスタンス変数についてかなり混乱しています。

私は、Aaron Hillegass の「Mac OS X 用の Cocoa プログラミング」の半分ほど読み終えたところで、すべてが論理的です。次のようなクラスを宣言します。

@class Something;

@interface MyClass : NSObject {
    NSString *name;
    NSArray *items;

    Something *something;

    IBOutlet NSTextField *myTextField;
}

@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSArray *items;
  • 他のオブジェクトは変数nameitemsインスタンス変数を操作する必要があるため、 @property/を使用@synthesizeしてそれらのアクセサー/ミューテーターを生成します。クラス内では、アクセサー/ミューテーターは使用しません。インスタンス変数を直接操作するだけです。

  • somethingクラスで使用する単なるインスタンス変数であり、他の誰もそれを使用する必要がないため、アクセサーとミューテーターのペアを作成しません。

  • UI でテキスト フィールドを操作する必要があるため、 を宣言しIBOutletて接続すれば完了です。

すべて非常に論理的です。

しかし、iPhone の世界では事情が異なるようです。人々はすべての単一インスタンス変数のプロパティを宣言し、 のプロパティを宣言し、アクセサ/ミューテータを使用してクラスIBOutletsのインスタンス変数とやり取りします(たとえば、ではなく書き込みます)。[self setName:@"Test"]name = @"Test"

なんで?何が起こっている?これらの違いは iPhone 固有のものですか? すべてのインスタンス変数のプロパティを宣言すること、 のプロパティを宣言することIBOutlets、および独自のクラス内でアクセサー/ミューテーターを使用することの利点は何ですか?

4

5 に答える 5

29

iPhone の世界では、利用できるガベージ コレクタはありません。参照カウントを使用してメモリを慎重に管理する必要があります。それを念頭に置いて、次の違いを検討してください。

name = @"Test";

self.name = @"Test";
// which is equivalent to:
[self setName: @"Test"];

事前に考慮せずにインスタンス変数を直接設定すると、以前の値への参照が失われ、保持カウントを調整できなくなります (release手動で設定する必要がありました)。プロパティを介してアクセスすると、新しく割り当てられたオブジェクトの保持カウントがインクリメントされるとともに、自動的に処理されます。

基本的な概念は iPhone 固有のものではありませんが、ガベージ コレクターのない環境では重要になります。

于 2009-10-11T22:33:03.853 に答える
6

プロパティは、インスタンス変数のアクセサーを生成するために使用されます。魔法のようなことはありません。

同じアクセサーを手動で実装できます。

メンバー変数の 3 つのメモリ管理戦略の例については、Aaron Hillegass の書籍を参照してください。彼らはassign/copy/retainです。特定の変数に必要ないずれかを選択します。

Objective-c でのメモリ管理を理解していると仮定します ...

アクセサーは、各変数のメモリ管理の複雑さと違いを隠します。

例えば:

name = @"Test"

は単純な代入ですが、name現在は への参照を保持していますNSString @"Test"copyただし、またはを使用することもできますretain。選択したメモリ管理のバージョンに関係なく、アクセサーは複雑さを隠し、常に次の方法で (または同様の方法で) 変数にアクセスします。

[self setName:@"Test"] 
[self name]

setName:は使えるかもしれassign/copy or retainませんし、気にする必要はありません。

私の推測では、iPhone のチュートリアルではプロパティを使用して、新しい開発者がメモリ管理を簡単に実行できるようにしています (ただし、プロパティを毎回手動で実装するのではなく、プロパティを使用して適切なアクセサを生成する方が便利ですが)。

于 2009-10-11T23:21:26.010 に答える
3

しかし、iPhone の世界では事情が異なるようです。人々はすべての単一インスタンス変数のプロパティを宣言し、 のプロパティを宣言しIBOutlets、アクセサ/ミューテータを使用してクラス内のインスタンス変数とやり取りします (たとえば、[self setName:@"Test"]ではなく書き込みますname = @"Test")。

これは iPhone 固有のものではありません。initメソッドとメソッドを除いて、dealloc常にアクセサーを使用することをお勧めします。特に Mac (Cocoa バインディングを使用) での主な利点は、アクセサーを使用すると無料の KVO 通知が得られることです。

人々が「インスタンス変数ごとにプロパティを宣言する」理由は、おそらく、すべてのインスタンス変数がプロパティとして公開したいものだからです。非公開にしたいものがある場合、ヘッダー ファイルでそのプロパティを宣言しません。(ただし、前述の無料の KVO 通知を取得するために、実装ファイルのクラス拡張でプロパティを作成する場合があります。)

私の意見では、アウトレットのプロパティを宣言するのはやり過ぎです。私はそれにポイントが表示されません。プロパティを作成しない場合、nib ローダーはインスタンス変数への直接アクセスによってアウトレットを設定しますが、これはそのタスクには問題ありません。

于 2009-10-12T04:55:29.513 に答える
2

現代の開発は、ベスト プラクティスを特定、定義、適用するために非常に強力な試みを行ってきたと思います。

これらのベスト プラクティスの中には、継続性と一貫性があります。

initおよびメソッドでのアクセサーの使用について議論することは別として、カプセル化、ポリモーフィック var 実装 (どちらも抽象化とリファクタリングを可能にする)deallocを含むアクセサーが提供する利点のために、アクセサーは通常 (クラスの内外で) 常に使用する必要があります。継続性と一貫性のベストプラクティスを促進します。オブジェクト指向言語の基本的な利点は、このように物事を行い、言語の機能を最大限に活用するときに発揮されます。上級プログラマーなら誰でも証明するように、自分のコーディングで常に一貫性を保つことは、しばしば過小評価される利点です。

于 2010-09-26T04:15:19.710 に答える
0

あなたはこのように書くことができます

//MyClass.h

@class Something;

@interface MyClass : NSObject 

@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSArray *items;

@end 

//MyClass.m
@interface MyClass() 

@property (nonatomic, strong) IBOutlet NSTextField *myTextField;
@property (nonatomic, strong) Something *something;

@end
于 2013-03-18T05:31:29.237 に答える