私はdrawonwardの答えに対する私のコメントで私が言ったことについて正しいです。
変数はコンテナです。変数は、その中にある値とは異なります。一般に、コードで変数の名前を使用する場合、実際には値を参照しています。と言うときは、変数自体を関数にfoo(bar)
渡すのではなく、変数に含まれる値を渡すことになります。bar
foo
bar
ローカル変数は、初期化しない限り、何にも初期化されません。したがって、ローカル変数に割り当てたり、以前に初期化したりせずに、ローカル変数を参照しないでください。ランダムな悪いことがランダムに起こります。
一方、インスタンス変数はに初期化され、何か他のものを入れるまでnil
含まれ続けます。nil
これは重要です。なぜなら、インスタンス変数init
には何も入れていないtestWindow
ので、インスタンス変数にはが含まれているからnil
です。
次に、と言うことで、通知を監視するオブジェクトとして、addObserver:… selector:… name:… object:testWindow
そのデフォルト値、を渡します。nil
これは、任意のオブジェクトの通知を監視することを意味します。
それはあなたが意味したことではありませんが、あなたが意味したことはあなたが書いたものではありません。あなたが意味したのは、テストウィンドウのオブザーバーとして自分自身を追加することです。ただし、まだテストウィンドウを作成しておらず、そのポインターをtestWindow
変数に配置していないため、作成したのは、任意のオブジェクトのオブザーバーとして自分自身を追加することです。
通知が発生した場合にのみ、ウィンドウを作成し(誤ってその時点で)、それを変数に割り当てます。これは、観察に影響を与えるには遅すぎます。割り当ては、その時点で変数にあったもの()を渡すことしかできなかったため、観察方法をさかのぼって変更することはありませんnil
。変数も、変数の将来の値も渡すことができず、渡すこともできません。
したがって、ウィンドウを作成し、の変数に割り当ててから、通知のオブザーバーとして自分自身を追加する必要がinit
あります。
コードでウィンドウを作成するには、2つの正しい方法があります。これはそのうちの1つであり、これはもう1つです。init
フレームの長方形がないため、プレーンを使用してウィンドウを作成しないでください。
または、さらに良いことに、これらすべてをコードで行う代わりに、IBを使用してウィンドウを作成します。testWindow
アウトレットを作成し、で観察を開始する必要がありますawakeFromNib
。
release
いずれにせよ、通知メソッドのウィンドウを破壊する(そしてそれによって破壊するか、少なくとも破壊しようとする)ため、もう一方の端にも問題があります。オブジェクトを破棄した後も、オブジェクトの通知を受信し続けることを期待しないでください。release
そのメッセージとnil
割り当てをコード内の別の場所に移動する必要があります。ウィンドウを一時的に非表示にするだけでなく、ウィンドウを本当に使い終えた場所に移動する必要があります。
要約すれば:
- そのメッセージを送信する前に、ウィンドウを作成し、そのポインタをの
testWindow
変数に割り当てます。init
addObserver:selector:name:object:
- ユーザーが表示および非表示にできるウィンドウの場合、ウィンドウの存続期間を表示/非表示の状態とは別にしてください。注文されたウィンドウオブジェクトがあっても問題ありません。注文したらすぐに破壊する必要はありません。とにかく、メモリはもうそれほど不足していません。Macではそうではありません。ウィンドウを本当に使い終わったときだけ、ウィンドウを解放します。おそらく、でウィンドウを解放します
dealloc
。
(ああ、スタイル/保守性の問題:@"TestNotification"
コード全体のようにリテラル文字列を振りかけないでください。どこかにその値を持つ変数を定義し、通知を使用するすべての場所でその変数を使用します。次に、文字列を変更するには、正確に1つの場所で変更し、変数の名前を変更するには、Xcodeのリファクタリングツールを使用できます。)