9

So I am writing a custom class that inherits from UIView. I have a bunch of subviews, that I add.

So run into 2 issues. IF I make the superview and subview references strong, the views are leaking. If I make them weak, they are not appearing at all. What am I doing wrong?

CustomUIView

@interface CustomUIView : UIView
@property(nonatomic, strong) AnotherCustomUIView *mySubView;
@end

@implementation CustomUIView {

- (void)initCommon {
    self.mySubView = [self createSubView]
}

- (AnotherCustomUIView *) createSubView {
    return [[AnotherCustomUIView alloc] init:self];
}

@end

AnotherCustomUIView

@interface AnotherCustomUIView : UIScrollView
@property (nonatomic, strong) CustomUIView *ownerView;
@end


@implementation AnotherCustomUIView

- (id)init:(CustomUIView *) ownerView {
    self = [super init];
    if (self) {
        self.ownerView = ownerView;
        self.delegate = self;
    }
    return self;
}

@end
nburk
  • 22,409
  • 18
  • 87
  • 132
user2453876
  • 303
  • 2
  • 12
  • 2
    Make one strong, the other weak, so you avoid retain cycles and premature deallocation. And for the love of God, don't call your initializer `init:`! –  Jul 07 '13 at 23:21
  • Yeah I just whipped up some code to demonstrate. The init is actually initWithOwner. AnotherCustomUIView is a virtual scrollview, it has the logic to calculate how big its content should be and respond to scroll, so I make itself he scrollview delegate. Should I be doing it differently? Would this cause memory issues? The delegate is supposed to be weak no? – user2453876 Jul 07 '13 at 23:50
  • @userXXX **exactly one of them** is supposed to be weak, practically it should not matter which one, but think about it a bit (after all, 'tis your own code), then decide which one you will make `strong`. –  Jul 07 '13 at 23:57

2 Answers2

10

Based on your code, I think you have a confusion between strong and weak references, and how those relate to memory management.

First, here is a great description of strong vs. weak: https://stackoverflow.com/a/11013715/700471

In your specific case, the ownerView property on AnotherCustomUIView should be weak as it is pointing to a senior object. Delegate references are also weak, I don't know that setting self.delegate = self; has any negative impact.

Edit:

To clarify, adding a view as a subview of another view creates a strong reference to it. Further strong references should not be necessary once your view is part of the view hierarchy. So you have this code:

[mySeniorView addSubView:myJuniorView]; // myJuniorView will not be released.
mySeniorView.juniorView = myJuniorView; // This shouldn't be a strong reference.

In the above code, if mySeniorView.juniorView is a strong reference, it's redundant. If you remove myJuniorView from the view hierarchy it won't be deallocated because you still have another strong reference to it. If .juniorView is a weak reference, then removing myJuniorView from the view hierarchy will cause it to deallocate and set .juniorView to nil.

That's why, for example, all of your IBOutlet properties should be weak; because the things in your xib that you're connecting them to are part of the view hierarchy and therefore will not dealloc because their senior views have strong references to them.

So, while I pointed out that your junior object should not have a strong reference to your senior object (neither one will deallocate; this is called a retain cycle and results in memory leaks) probably your senior object shouldn't have a strong reference to your junior one, unless you want it to hang around even when it's not in the view hierarchy. These are views, after all; I would say create your junior object, pop it into the view hierarchy and then save a reference to it in a weak property so you can access it for as long as it exists. Then, when you remove it from the view hierarchy, your reference nils out.

Anyway, hope that helps.

Reference: Apple Docs, addSubview:

Community
  • 1
  • 1
Matt Mc
  • 8,882
  • 6
  • 53
  • 89
  • Thanks - I guess the confusion came from my belief that adding the ownerView to its own superView would inherently create a strong reference, so I would be ok if I made both references weak, but I will do as you suggest, it makes sense, and was the direction I was headed in anyway. Thanks for confirming. – user2453876 Jul 08 '13 at 00:03
  • Hm...Adding a view as a subview to another view does create a strong reference. I edited my post to clarify a bit. – Matt Mc Jul 08 '13 at 00:49
  • 1
    I don't see a downside to holding multiple strong references to an owned object. They're free and they're all decremented upon deallocation of the owner. Weak references are also more expensive since the system needs to track them to fulfill the auto-nil contract... – Adam Kaplan Jul 07 '17 at 05:15
2

Almost always the reference to the parent should be weak. This is typical chain of command. The parent creates and "owns" the child, and the child merely observes its parent. You want the child to be existentially dependent upon the parent, not the other way around.

devios1
  • 36,899
  • 45
  • 162
  • 260