0

enter image description here

I'm a beginner and still trying to figure out how to read this. There are 3 custom views and at the start I allocate the first one. And then the second / deallocate the first and then the third / deallocate the second.

I do empty/nil all arrays right before deallocating each view so from what I see, all memory retained each time I allocated views, should be released whenever I deallocate/nil them but in the graph it keeps increasing, I don't see anything being released at all.

Is that supposed to look like that? I'm nil-ing delegates, arrays, dictionaries etc everything.

-(void)firstTOsecond {

[self.first removeFromSuperview];
self.first.delegate = nil;
self.first = nil;


self.second = [[Second alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
[self.view addSubview:self.second];
self.second.delegate = self;}

-(void)secondTOthird {

[self.second removeFromSuperview];
self.second.delegate = nil;
self.second = nil;


self.third = [[Third alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
[self.view addSubview:self.third];
self.third.delegate = self;}

EDIT

In First.m / Second.m / Third.m

-(instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
    self.buttonStartFrame = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"buttonStartFrame"]];
    [self addSubview:self.buttonStartFrame];
    self.buttonStartFrame.userInteractionEnabled = YES;
    self.buttonStartButton = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"buttonStartDefault"]];
    [self.buttonStartFrame addSubview:self.buttonStartButton];
    self.buttonStartButton.userInteractionEnabled = YES;
    self.labelStart = [[UILabel alloc]init];
    [self.buttonStartButton addSubview:self.labelStart];
    self.labelStart.textColor = [UIColor darkGrayColor];
    self.labelStart.text = @"Start";
    }
return self;}
durazno
  • 559
  • 2
  • 7
  • 25
  • are you reusing elements or creating new instances ? – aug2uag May 17 '16 at 02:06
  • Edited my question. By reusing and creating new instances you mean something like that in VC? That's what I'm doing. – durazno May 17 '16 at 02:11
  • yeah, setting the views to nil won't deallocate them .. read up on how ARC handles memory management .. it's also good practice to create a class or method to create and update views, instead of creating a new one .. assigning delegate, etc .. `[view removeFromSuperview]` followed by adding the same view (i.e. for all intensive purposes) is not the way to go .. reuse your views ! – aug2uag May 17 '16 at 02:44
  • Can you share the code for your `Second` class? It's hard to answer your question without looking at the actual class being deallocated – jrhee17 May 17 '16 at 02:53
  • @aug2uag I have read a bunch about ARC including threads on SO but found nothing but nil-ing objects. What else's there to be done? And by reusing you mean create one view instance and when transitioning to others do this? self.sharedView = [Second alloc]init]; – durazno May 17 '16 at 03:05
  • @jrhee17 I create a few UIImageViews inside that's it. – durazno May 17 '16 at 03:07
  • ARC cannot handle reference cycles. If your mystery class create such one ARC won't be able to deallocate the object. – Uri Brecher May 17 '16 at 03:09
  • @UriBrecher I'm aware of reference cycles but that's not it. My "mystery class" really does nothing but display a few images. – durazno May 17 '16 at 03:12
  • Not sure but that memory could be occupied by kernel resources. Sometimes its not enough to rely on ARC but instead you have to explicitly free the resource by calling a certain library function. E.g. When your done with a file you have to explicitly call close. Maybe you have something similar here. – Uri Brecher May 17 '16 at 03:16
  • @aug2uag Could you please post some examples explaining what you're saying that'd be very helpful thanks. – durazno May 17 '16 at 03:21
  • 2
    The code sequence `self.first = nil; self.first.delegate = nil;` isn't going to do what I assume you think it will. After the first assignment you've no reference to whatever object `self.first` referenced, so the second assignment is not going to set that object's `delegate`. This doesn't error as dot notation translates to method calls and you can message `nil` without error - it just does nothing. Check you're not making the same mistake elsewhere (it occurs twice in your question). HTH – CRD May 17 '16 at 04:21
  • @CRD Just added the code I have in self.first. That's all I have in there so I really am not sure what the mistakes could be.. – durazno May 17 '16 at 04:56
  • 1
    You have to set any delegate refs to nil before you set the actual object to nil, the reason you are leaking memory is due to ref count cycles in your code. ARC is not going to "fix" any of this for you. A better design is to simply not hold refs from one view controller to another. – MoDJ May 17 '16 at 05:01
  • @MoDJ I know that... I'm fully aware but doing it wrong. That's why I'm setting the delegate refs to nil by self.first = nil; and then self.first.delegate = nil; but you're saying I should set self.first.delegate to nil before self.first? Just tried that but still the same. Also I'm only using one VC. – durazno May 17 '16 at 05:11
  • You don't have anything "in `self.first`", it is a property which presumably references an object and the code you show is associated with that object. Let's call that object X. X also has a property `delegate`. After you do `self.first = nil` you lose the reference to X, so when you then do `self.first.delegate = nil` you are **not** changing X's `delegate` property. Before you try to solve your leak you really need to sort out such mistakes in your code, you seem to be confused over what assigning to a property actually does. HTH – CRD May 17 '16 at 05:35
  • @CRD Yeah I got that from MoDJ's comment and so I tried setting self.first.delegate = nil BEFORE self.first = nil but that didn't help either. – durazno May 17 '16 at 05:51
  • @CRD Also I'm not confused at all actually I said it wrong I meant to say "in First.m" and of course self.first is a property that references an object. So any other suggestions besides setting the delegate refs to nil before the actual objects? – durazno May 17 '16 at 06:03
  • @durazno Are your delegate strong?? If yes make them weak and try again... – Akshay Nalawade May 17 '16 at 12:33
  • Nope and I am aware of that. They're weak and always have been. Any other suggestions..? – durazno May 18 '16 at 05:34
  • @durazno what are you trying to build, custom cell views ? – aug2uag May 18 '16 at 18:31
  • @aug2uag I've built 3 separate custom views instead of 3 VCs and I also custom animate their transitions among a bunch of other stuffs in each view(CAAnimation not block based UIView Animation). One as welcome page, the second as settings page and the third as main page. After you're suggestion, I'm planning on merging all 3 into 1 and create a huge custom view that serves for all 3 purposes just because that way I can reuse one instance instead of creating 3 separate properties but this still does not help me find out why the memory isn't being released when everything should be done is done – durazno May 19 '16 at 04:05
  • @aug2uag But now that I think about it, merging all 3 into 1 wouldn't be worth it bcuz that'd be like, trying to shove everything in VC and ignore MVC. I'm using these custom views as VCs and that suggestion of yours doesn't really make sense or did I miss something? I just need to find out why exactly the memory isn't being released. I don't think the structure is causing the leak. – durazno May 19 '16 at 04:24
  • For what you described, a splash page, a settings page, and a main page .. i would have them as three separate view controllers .. the custom views .. for instance a custom UITextField .. need to be handled appropriately .. in the case where it's set only once you don't have to worry about memory management, and instead worry about not creating multiple instances of your view controllers – aug2uag May 19 '16 at 20:06
  • @aug2uag So you're saying there actually is no leak..? The increment I see in the graph is just what's supposed to happen with allocations of 3 custom views I have? – durazno May 20 '16 at 02:03
  • @aug2uag Because views can be animated however I want making the whole thing as customized as possible unlike View Controllers, I'll still go with custom views instead. – durazno May 20 '16 at 02:31
  • same over, the semantics of uiview vs uiviewcontroller doesn't change the simple fact that if you keep allocating, the heap will rise .. the underlying issue is lack of recycling elements where they're necessary .. i'll work on an answer for you below to show you what i mean – aug2uag May 20 '16 at 05:49

1 Answers1

0

the memory leak could be that you are continuously creating new view elements when they could be updated instead .. you can create helper methods to avoid allocating new views, and updating the one's on the main thread instead

- (void)limitedUpdateTextColorView:(NSDictionary *)somethingCache {
    self.labelStart.textColor = [somethingCache valueForKey:@"bar"];
    self.labelStart.text = [somethingCache valueForKey:@"foo"];
}
aug2uag
  • 3,379
  • 3
  • 32
  • 53
  • I thought about what you've suggested but then there's delegates. Each custom view has its own delegate methods to assign/call and so I can't share one property for all 3 cuz some of the delegate methods are called in between transitions when 2 views existe on screen at the same time. I know what your'e saying but it doesn't work for me. – durazno May 20 '16 at 06:12
  • what do you mean there's delegates ? without more detail all i can tell you is this should not affect the fact there are delegates .. i suggest you read on programming patterns, and in this case OOP is a good study .. check out factory patterns and metaprogramming .. it's all about reuse and DRY – aug2uag May 20 '16 at 08:34
  • I really don't know what you mean by "reusing". Do you mean I should create one shared property for 3 objects? That doesn't even work so I'm assuming that's not it then what is it?! I'm allocating 3 separate views because I need 3 of them at once at the same time and you're saying I should create only one property for all of them? How does that work? I'm so confused. – durazno May 22 '16 at 08:25
  • reusing simply means: do not allocate new objects identical or near identical to objects that exist, not only do you block the main thread, you also create memory leaks – aug2uag May 22 '16 at 08:48
  • But that I already knew.. I've been saying that over and over and over but you've been telling me the same thing over and over.. the objects I need to have presented simultaneously are completely different and all the objects that are either identical or almost identical are being reused. This whole time you've been telling me things I'm already aware of and applying to. – durazno May 22 '16 at 17:22
  • your request is cryptic without explicitly showing what you're having trouble to do, your feedback indicated that you were allocating new objects when they should not have been allocated as a possible solution for your problem – aug2uag May 22 '16 at 22:42
  • if you're dealing with views, allocate them once, and switch views with UIView transition view or the lower level method you may have mentioned above, don't try to deallocate and remove manually especially while using ARC, or create a factory with updates such as the one i provided above – aug2uag May 22 '16 at 22:45