Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice for custom UIView subview strong vs weak

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
like image 832
user2453876 Avatar asked Jul 07 '13 23:07

user2453876


2 Answers

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:

like image 110
Matt Mc Avatar answered Nov 15 '22 23:11

Matt Mc


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.

like image 21
devios1 Avatar answered Nov 16 '22 00:11

devios1