2012-03-17 14 views
7

プロパティで保存された2つのサブビューを私のビューに追加します。私のビューにサブビューを追加すると、私のsetupメソッドが呼び出された後、サブビューが一見外されてしまいます。最終的には、ビューは決して表示されません。今、weakとは対照的に、プロパティをstrongに変更すると、ビューへの参照が保持され、画面に表示されます。だからここで何が起こっているの? addSubview:insertSubview:にサブビューが保持されないのはなぜですか?私はなぜaddSubviewはビューを保持していませんか?

#import "NoteView.h" 
@interface NoteView() <UITextViewDelegate> 
@property (weak, nonatomic) HorizontalLineView *horizontalLineView; // custom subclass of UIView that all it does is draw horizontal lines 
@property (weak, nonatomic) UITextView *textView; 
@end 

@implementation NoteView 
@synthesize horizontalLineView = _horizontalLineView; 
@synthesize textView = _textView; 

#define LEFT_MARGIN 20 
- (void)setup 
{ 
    // Create the subviews and set the frames 
    self.horizontalLineView = [[HorizontalLineView alloc] initWithFrame:self.frame]; 
    CGRect textViewFrame = CGRectMake(LEFT_MARGIN, 0, self.frame.size.width, self.frame.size.height); 
    self.textView = [[UITextView alloc] initWithFrame:textViewFrame]; 


    // some addition setup stuff that I didn't include in this question... 

    // Finally, add the subviews to the view 
    [self addSubview:self.textView]; 
    [self insertSubview:self.horizontalLineView atIndex:0]; 
} 

- (void)awakeFromNib 
{ 
    [super awakeFromNib]; 

    [self setup]; 
} 

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     // Initialization code 
     [self setup]; 
    } 
    return self; 
} 
+0

作成する方法NoteViewのインスタンス?コントロールがセットアップに到達しているのを参照してください。 –

+0

私は、それをストーリーボードのビューコントローラに追加することによって、NoteViewのインスタンスを作成しています。 –

+0

クラスがXibでNoteViewとして指定されています –

答えて

21

はここにあなたのコードの行です:

self.horizontalLineView = [[HorizontalLineView alloc] initWithFrame:self.frame]; 

リコールをhorizontalLineViewプロパティが弱いこと。 ARCが生成する余分なコードを使って、実際にその行で何が起こっているかを見てみましょう。まず、あなたは強い参照取り戻す、allocinitWithFrame:メソッドを送信します。この時点で

id temp = [[HorizontalLineView alloc] initWithFrame:self.frame]; 

を、HorizontalLineViewオブジェクトは、ドットシンタックスを使用しているためhorizontalLineViewプロパティを設定するために、1次の保持カウントを持っています、コンパイラはメソッドをselfに送信するコードを生成し、tempをパラメータとして渡します。 HorizontalLineViewプロパティはweakを宣言されているので、セッターメソッドは、この処理を行います。

tempに等しい self->_horizontalLineViewを設定し、弱参照のオブジェクトのリストに &self->_horizontalLineView置く
objc_storeWeak(&self->_horizontalLineView, temp); 

。しかしではなく、HorizontalLineViewオブジェクトの保持カウントをインクリメントするのはです。ゼロにHorizontalLineView、オブジェクトの保持カウントを下げる

[temp release]; 

をので、オブジェクトの割り当てを解除:temp変数が不要になったので

最後に、コンパイラはこれを生成しません。割り当てを解除するとき、弱参照のリストを調べ、それぞれをnilに設定します。したがって、self->_horizontalLineViewnilになります。

この問題を解決する方法は、あなたがその寿命を延ばすことができるようにあなたがそれを保持してスーパーにHorizontalLineViewオブジェクトを追加した後まで、temp変数明示することです。

HorizontalLineView *hlv = [[HorizontalLineView alloc] initWithFrame:self.frame]; 
self.horizontalLineView = hlv; 
// ... 
[self insertSubview:hlv atIndex:0]; 
+2

うわー - あなたは絶対に正しいです!これは私がシーンの背後で起こっていることについて私が望んでいた正確な種類の説明です。明示的な変数を作成する余分なステップを経なければならないのですが、それは奇妙に見えますか?いずれにせよ、助けてくれてありがとう! –

+0

一時変数を導入するだけで十分であることが分かったので、 'insertSubview'の呼び出しでそれを使う必要はありません。したがって、あなたは '[self insertSubview:self.horizo​​ntalLineView atIndex:0];を使うことができ、それでも動作します。これは私にとって直観的ではないようです。あなたはこの行動を説明できますか? –

3

弱いが、親子がサイクルを維持する例でない限り、使用すべきではないARCで(それゆえ強いと弱いものを)iOS5をを使用​​しています、ところで

されています。以下のコードを参照してください。形成された(親は子への参照を保持し、子は親への参照を保持するので、どちらもdeallocされません)。 StrongはARCと同等のARC(ARCの下では無効)です。弱い参照よりもずっと長い時間オブジェクトの安定したポインタを保持します。したがって、addSubviewは実際に何らかのエラーを出すのではなく実際に動作します。

なぜaddSubview:とinsertSubview:サブビューを保持しないのですか?

nilオブジェクトでretainを呼び出そうとしたことがありますか?うん、まだ無し。あなたの弱い参照は、UIViewオブジェクトをオブジェクトの上に「呼び出し保持」するのに十分な長さに保つわけではありません。

+0

なぜクラッシュしますか? –

+0

私は解放されたインスタンスに保持を送信すると仮定します... – CodaFi

+0

ビューが保持されるのに十分な長さに保たれない方法についてあなたが言っていることを見ていますが、(親)ビューの後にセットアップメソッドを呼び出す必要があります。インスタンス化されます。だから、ビュー階層にサブビューを追加すると、それらは保持されますよね?だから私はまだここで混乱していると思う。私は何が欠けていますか? –

0

代わりにこれを使用してみてください:

@property (nonatomic, retain) 
+0

弧の下で保持が無効であり、彼は説明を求めていました。 – CodaFi

+0

@CodaFi、retainプロパティはARCで完全に有効です。 –

関連する問題