2009-08-03 1 views
53

私はIBOutletsの次のセットアップを参照してください。IBOutletはプロパティで合成する必要がありますか?ほとんどの例では



(Example A) 

FooController.h: 

@interface FooController : UIViewController { 
    UILabel *fooLabel; 
} 

@property (nonatomic, retain) IBOutlet UILabel *fooLabel; 

@end 

FooController.m: 

@implementation FooController 

@synthesize fooLabel; 

@end 

しかし、これはまた、正常に動作します(予告:なしプロパティなしのsynthesize):



(Example B) 

FooController.h: 

@interface FooController : UIViewController { 
    IBOutlet UILabel *fooLabel; 
} 

@end 

FooController.m: 

@implementation FooController 

@end 

は定義IBOutletsのいずれかの欠点が通りあります実施例Bでは?メモリリークのような?うまく動作するように見えますが、私はIBOutletをパブリックプロパティとして公開しないことを好みます。これは、コントローラの実装でのみ使用されます。本当の必要がない3つの場所でそれを定義することは私に非常にドライ(あなた自身を繰り返さないでください)と私を打つことはありません。

答えて

94

、IBOutletsは、次のように接続されています

  1. <OutletName>を設定すると呼ばれるメソッドを探します。存在する場合はそれを呼び出します。
  2. メソッドが存在しない場合は、<OutletName>という名前のインスタンス変数を探し、を保持せずにに設定します。 iPhone OS上で

、IBOutletsは、次のように接続されています

  1. コール[オブジェクトのsetValue:outletValue forKey: "<OutletName>" @]

キーの設定値の振る舞い

  1. set <という名前のメソッドを探します。 OutletName >:。存在する場合はそれを呼び出します。
  2. メソッドが存在しない場合は、<OutletName>という名前のインスタンス変数を探し、を保持し、を保持します。

あなたがプロパティを使用する場合は、「<OutletName>セットと呼ばれる方法のためにルック:...」に分類されます両方のプラットフォーム上でケースを。インスタンス変数を使用するだけの場合は、Mac OS X VS iPhone OSで保持/解放の動作が異なります。インスタンス変数を使用することには何も問題はありません。プラットフォーム間で切り替えるときの動作の違いを処理するだけで済みます。

ここには、このトピックに関する完全なドキュメントへのリンクがあります。 http://developer.apple.com/documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html#//apple_ref/doc/uid/10000051i-CH4-SW6

+0

こんにちは、詳細な回答ありがとうございます!非常に役に立ちます –

+0

変数名がプロパティ名と異なる場合はどうなりますか?違うかどうか? –

+0

上記の "OutletName"という名前は、ソースコードの "IBOutlet"キーワードの隣にあるものとして定義されています。 IBOutletが@propertyにある場合、セッターが見つかるので、インスタンス変数の名前は関係ありません。何らかの理由でセッターが存在しない場合は、コンセントを接続するときに例外が発生します。 IBOutletキーワードがインスタンス変数にあり、一致しない名前のセッターが存在する場合、セッターは呼び出されません。 –

4

最終結果はまったく同じですが、心の中でいくつかのことを維持する必要があります:

  • 店としてインスタンスフィールドを使用して、あなたはのdeallocでそれらを解放しないでください。

  • (保持)属性を持つプロパティを使用している場合、あなたはのdeallocself.property=nilやバッキング変数を解放することによってを使用して)でプロパティを解放しなければなりません。これにより、何が起こっているかについてより透明になります。

実はそれはすべて同じ古いルールにダウンしています:「なたは、あなたがのalloc/を保持何解放」。だからあなたがアウトレットとしてインスタンスフィールドを使用する場合、あなたはそれを解放してはいけないので、あなたはそれを確保/保持しませんでした。 Mac OS Xで

+5

このアドバイスはMac OS Xでは正しく表示されますが、iPhone OSでは正しく表示されません。下の私の答えを見てください。 –

+1

deallocメソッドで "self.property = nil"を呼び出すのは良い方法ではありません。 initまたはdeallocからメソッドを呼び出すべきではありません。もしサブクラス化されていれば、サブクラスは解放された後、またはinitされる前にそれらのsetterがdurringと呼ばれることを期待していないでしょう。 –

+0

インスタンス変数の合成を使用する自動保持プロパティを解放する方法は、(バッキングフィールドを明示的に宣言することなく)解除する唯一の方法です。あなたは、選択肢、良い練習、またはしていない。 –

12

Mac OS Xでは、IBOutletはデフォルトでは保持されません。これは、iPhone OSの動作とは逆です。iPhone OSでは、プロパティを宣言しない場合は保持され、deallocメソッドでこのプロパティを解放する必要があります。さらに、64ビットのランタイムは、プロパティ宣言を使用してインスタンス変数を合成できます。つまり、いつかインスタンス変数(IBOutlet)を省略することができます。

これらの理由から、常にプロパティを作成してプロパティ内でIBOutletを使用すると、より均質で互換性があります。残念ながら、これはもっと冗長です。

最初の例では、常にコンセントをdeallocメソッドで解放する必要があります。 2番目の例では、iPhone OSのみでコンセントを解放する必要があります。

1

サンプルコードがプログラムでUILabelを割り当てて初期化してからUIViewに追加するため、これらの例ではretainを使用する可能性があります。 Interface Builderを使用する方法を学ぶことは、しばしばその点ではないので、多くの例がそうです。

IBOutletをラベルやその他のビューにドラッグすることで、開発者がInterface Builder内のUILabel(ボタン、ビューなど)を '割り当てる'場合、IBOutletを使用する2番目の例(プロパティなしと合成なし)が使用されます成分。私の意見では、前述のドラッグ・アンド・ドロップ操作(Label on View)は、サブビュー、ラベルをビューに追加するなどです。ラベルはビューによって保持されます。ビューはウィンドウによって保持されます。ウィンドウはFile's Ownerによって保持されます。ファイルの所有者は通常、メインで起動されるドキュメントです。あなたはfooLabelが既にメモリアドレスを持っているawakeFromNib

- (void)awakeFromNib 
{ 
    [fooLabel blahblah]; 
} 

を追加することによって、(あなたがプログラムをステップ実行するときに注意します。

ザッツをラベルは、ファイルバンドルから初期化されたため、

( (つまり、IBOutletメソッドについてはまだ話しています)

また、上記のiOS me thodはKey Valueメソッドを使用します。

call [object setValue:outletValue forKey:@"<OutletName>"] 

これはObserver/Observableパターンです。このパターンでは、Observableオブジェクト参照がSet/Array内のObserverを必要とします。値の変更はSet/Arrayを反復し、すべてのオブザーバを均等に更新します。そのセットはすでに各Observerを保持しており、iOSには保持されていません。

さらに残りは推測です。

あなたがして

@property (nonatomic, retain) IBOutlet UILabel *fooLabel; 

をInterface Builderのを使用しない場合は、おそらくIBOutlet UILabel * fooLabel(非アトミック、割り当てる)

@property (nonatomic, weak) IBOutlet UILabel *fooLabel; 

または @propertyに変更する必要がありますようです。

そして、deallocメソッドで解放する必要はありません。さらに、OSXとiOSの要件を満たします。

これは論理に基づいており、私はここでいくつかの部分が欠落している可能性があります。

しかし、ビューがプログラムの寿命を通して永続的であるかどうかは関係ありません。モーダルダイアログボックス(開いた状態、閉じた状態、開いた状態、閉じた状態)のラベルは実際には1サイクルにつき過度に保持され、リークすることがあります。これは、閉じられた各ダイアログボックスがファイルシステムにシリアライズされ、x、yの位置とサイズ、サブビューなどが維持されるためです。その後、デシリアライズされます。次のセッションでオープンされます(minimiz