[解決済み] iOSの合成されたプロパティの名前を、先頭のアンダースコアで変更するのはなぜですか?重複
質問
重複の可能性があります。
cocoa objective-cクラスの変数の前にあるアンダースコアはどのように動作しますか?
Xcode 4で新しいプロジェクトを作成するとき、ボイラープレートコードは、実装ファイル内のivarsをasで合成するときにアンダースコア文字を追加します。
@synthesize window = _window;
または
@synthesize managedObjectContext = __managedObjectContext;
ここで何が達成されているのか、誰か教えてください。私は完全な田舎者ではありませんが、これは私が理解していないobjective-Cの1つの側面です。
アプリのデリゲート実装では、上記のようにウィンドウのiVarを合成した後、アプリケーションのdidFinishLaunchingWithOptions:メソッドでウィンドウとviewControllerのivarはselfを使って参照されています。
self.window.rootViewController = self.viewController
[self.window makeKeyAndVisible];
が、deallocメソッドでは_window、または_viewControllerです。
ありがとうございます。
どのように解決するのですか?
これは、以前のバージョンの Objective-C ランタイムの成果物です。
元々は
@synthesize
はアクセサメソッドを作成するために使用されていましたが、ランタイムはまだインスタンス変数を明示的にインスタンス化する必要がありました。
@interface Foo : Bar {
Baz *_qux;
}
@property (retain) Baz *qux;
@end
@implementation Foo
@synthesize qux = _qux;
- (void)dealloc {
[_qux release];
[super dealloc];
}
@end
人はインスタンス変数にプレフィックスをつけて、プロパティと区別する(Appleはアンダースコアを使うことを望んでいないけれど、それは別の問題)。インスタンス変数を指すようにプロパティを合成するのです。しかし、そのポイントは
_qux
はインスタンス変数であり
self.qux
(または
[self qux]
) は、メッセージ
qux
オブジェクトに送られる
self
.
インスタンス変数を直接
-dealloc
でインスタンス変数を直接使用しています。代わりにアクセサメソッドを使用すると、次のようになります(ただし、まもなく説明する理由により、私はこれを推奨しません)。
- (void)dealloc {
self.qux = nil; // [self setQux:nil];
[super dealloc];
}
これは
qux
を解放すると同時に、参照をゼロにする効果があります。しかし、これは不幸な副作用を持つことがあります。
-
予期しない通知を発行することになるかもしれません。他のオブジェクトは
qux
への変更を観測している可能性があり、アクセッサメソッドで変更されると記録されます。 -
(この点については誰もが同意しているわけではありません:) アクセッサが行うポインタのゼロ化は、プログラムのロジック エラーを隠す可能性があります。もしあなたが、あるオブジェクトのインスタンス変数にアクセスすることがあれば
の後に
の後に、オブジェクトが解放された場合、何か重大な間違いを犯していることになります。なぜなら、Objective-Cの
nil
-メッセージングのセマンティックスのため、あなたは決して知ることができませんが、アクセサを使ってnil
. もし、インスタンス変数を直接解放し、参照をゼロにしなかったら、解放されたオブジェクトにアクセスすることで、大音量のEXC_BAD_ACCESS
.
ランタイムの後のバージョンでは、アクセッサメソッドに加えて、インスタンス変数を合成する機能が追加されました。これらのバージョンのランタイムを使えば、上記のコードはインスタンス変数を省略して書くことができる。
@interface Foo : Bar
@property (retain) Baz *qux;
@end
@implementation Foo
@synthesize qux = _qux;
- (void)dealloc {
[_qux release];
[super dealloc];
}
@end
これは実際にインスタンス変数を
Foo
という
_qux
と呼ばれ、ゲッターとセッターのメッセージによってアクセスされます。
-qux
と
-setQux:
.
これは少し面倒ですが、アンダースコアを使用する良い理由があります。もしあなたが、生のインスタンス変数とアクセッサメソッドのどちらを使用しているか覚えていると自分自身を信じることができると思うなら、代わりにこのようにすればいいのです。
@interface Foo : Bar
@property (retain) Baz *qux;
@end
@implementation Foo
@synthesize qux;
- (void)dealloc {
[qux release];
[super dealloc];
}
@end
そして、インスタンス変数に直接アクセスしたい場合は、次のように記述します。
qux
(とすればよいのです(訳すと
self->qux
に変換されます)。アクセサメソッド(オブザーバに通知したり、他の面白いことをしたり、 メモリ管理に関してより安全で簡単にする)を使いたいときは
self.qux
(
[self qux]
) と
self.qux = blah;
(
[self setQux:blah]
).
ここで悲しいのは、Appleのサンプルコードとテンプレートコードは最悪だということです。適切な Objective-C スタイルのガイドとしては決して使用せず、適切なソフトウェア アーキテクチャのガイドとしても絶対に使用しないでください。)
関連
-
[解決済み] Androidのチュートリアルで、ほとんどのフィールド(クラスメンバー)が`m`で始まるのはなぜですか?
-
[解決済み] PHP のクラスメソッドの先頭のアンダースコアはどうなっているのでしょうか?
-
[解決済み] 現在の日付から7日分を差し引いた日数
-
[解決済み] Objective-Cのクラス→文字列のようなものです。[NSArray className] -> @"NSArray" のようになります。
-
[解決済み] Objective-Cで配列に結合する
-
[解決済み] error: Writeable atomic property cannot pair with synthesized setter/getter and the user defined setter/getter.
-
[解決済み] 角括弧 < > と引用符 " " を使って #import する。
-
[解決済み] Xcodeはクラッシュの原因となる行を表示しない
-
[解決済み] メソッドが存在するかどうかをチェックする
-
[解決済み] 別のUIViewの下にあるUIViewとのインタラクションを許可する
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] cocoa objective-cのクラスで変数の前にアンダースコアを付けるとどうなるのでしょうか?
-
[解決済み] 現在の日付から7日分を差し引いた日数
-
[解決済み] Objective-Cで配列に結合する
-
[解決済み] 角括弧 < > と引用符 " " を使って #import する。
-
[解決済み] RootViewControllerのスイッチングアニメーション
-
[解決済み] Objective-CのクラスでSwiftのプロトコルをインポートする
-
[解決済み] Objective-Cです。カテゴリ内のプロパティ/インスタンス変数
-
[解決済み] IOSのUIViewからアプリケーションのドキュメントフォルダに画像を保存する
-
[解決済み] performSelectorの使用: メソッドを呼び出すだけと比較した場合
-
[解決済み] キーチェーンのアイテムは何がユニークなのか(iOSの場合)?