Why addSubview: not save view?

I add to my view two subsets that are stored in properties. When adding subzones to my view, subViews seem to be freed up after calling the setup method. The end result is that views are never displayed. Now, if I change my properties to strong rather than weak , I will save the link to the views and they will now be displayed on the screen. So what's going on here? Why do addSubview: and insertSubview: not save subviews? See code below:

btw, I use iOS5 with ARC (hence the strong and weak stuff)

 #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; } 
+7
source share
3 answers

Here is the line of your code:

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

Recall that the horizontalLineView property is weak. Let me go through what really happens on this line, with the extra code that ARC generates. First you send the alloc and initWithFrame: methods, returning a strong link:

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

At this point, the horizontalLineView object has a save value of 1. Further, since you used the dot syntax to set the horizontalLineView property, the compiler generates code to send the setHorizontalLineView: method to self , passing temp as a parameter. Since the horizontalLineView property is declared weak , the setter method does this:

 objc_storeWeak(&self->_horizontalLineView, temp); 

This sets self->_horizontalLineView to temp and puts &self->_horizontalLineView into the list of weak link objects. But it does not increment the save counter of the horizontalLineView object.

Finally, since the temp variable is no longer needed, the compiler generates this:

 [temp release]; 

This lowers the value of the horizontalLineView to zero, so it frees the object. At the time of release, he iterates over the list of weak links and sets each of them to nil . So self->_horizontalLineView becomes nil .

The way to fix it is to make the temp variable explicit so that you can extend its lifetime until you add a horizontalLineView object to your supervisor that saves it:

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

The weak one should not be used if only in cases where a cycle has been created to save the parent child, the parent holds a link to the child, the child keeps a link to the parent, so none of them is dealloc'd). Strong is the ARC equivalent to save (now invalid with ARC) and maintains a good stable pointer to an object for a much longer period of time than a weak reference, so addSubview actually works, and does not give you any kind of error.

Why are adding addSubview: and insertSubview: not saved by the view?

Have you ever tried to cause hold to zero? Yes, not yet. Your weak link does not hold the UIView object long enough to successfully "cause hold" on the object.

+3
source

Try using this instead:

  @property (nonatomic, retain) 
0
source

All Articles