0

Please see attached image for reference. All of the viewControllers have been already removed from the app but Memory Debugger shows its instances as well as all its properties. When i click the Show Only Leaked blocks filter of Memory Debugger, the viewControllers and other instances do not appear in it. Does it mean there are no leaks?

How do I solve the problem. What does it mean?

enter image description here

I do have the PKYStepper block in the CartViewController's cellForRowAtIndexPath (Stepper is a UIControl in my TableViewCell) method as follows :

PKYStepper *qtyStepper = [cell viewWithTag:993];

qtyStepper.tappedCallback = ^(PKYStepper *stepper) {

            NSLog(@"Tapped!");

            rowSelected = indexPath;

            if (((Dish*)((MenuSubSection*)_section.subSections[0]).dishesArray[indexPath.row]).disheOptions.count)
            {
                UIWindow *window = [UIApplication sharedApplication].keyWindow;

                NSBundle* bun = [NSBundle bundleWithIdentifier:@"com.test.test"];

                DishItemOption *dishOptions = [[bun loadNibNamed:@"DishItemOption" owner:self options:nil] objectAtIndex:0];
                dishOptions.frame = CGRectMake(0, 0, window.frame.size.width, window.frame.size.height);

                dishOptions.dish = [[Dish alloc] initWithDishObject:((Dish*)((MenuSubSection*)_section.subSections[0]).dishesArray[indexPath.row])];
                dishOptions.delegate = self;
                [window addSubview:dishOptions];
            }

        };

How to make it reference the Weak Self?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Hyder
  • 1,163
  • 2
  • 13
  • 37
  • Are you sure those view controllers were deallocated? Note that even if a view controller is no longer on screen, it doesn't mean that there aren't any other strong references that keep it alive. – Cristik Sep 29 '19 at 14:35
  • Well I call `[self dismissViewControllerAnimated:YES completion:nil];` which should dismiss all viewControllers in the stack right? Assuming the presented view Controller is a Navigation View Controller. – Hyder Sep 29 '19 at 16:27
  • 2
    Well, dismissing a view controller doesn't guarantee that the view controller will be deallocated, just that the controller won't be anymore part of the UI hierarchy. If some one else keeps a strong reference to the controller, that reference will keep it alive. And looking at the image you posted, looks like a block is the one keeping the controller alive - it might well be a retain cycle over there. – Cristik Sep 29 '19 at 19:09
  • Found the block and pasted it in the question. Can you suggest how to fix the retain cycle? – Hyder Sep 30 '19 at 07:00
  • 1
    https://stackoverflow.com/questions/50261303/swift-closures-causing-strong-retain-cycle-with-self – Cristik Sep 30 '19 at 09:39

2 Answers2

3

It looks like you've likely captured the view controller in a callback block of some sort.

Specifically, PKYStepper seems to have a callback block that is strongly referencing the view controller. Either make sure said reference is weak or make sure the block is properly destroyed when the view controller is torn down.

bbum
  • 162,346
  • 23
  • 271
  • 359
  • 1
    A common pattern is also to use a `weak self` in `@escaping` closures, to avoid retain cycles, like: `obj.closure = { [ weak self ] in ... }` – Macmade Sep 29 '19 at 23:46
  • @bbum You are right. I do have the PKYStepper callback in that View Controller but I don't know how to make it reference Weak Self. Have added the block in my question. Any help will be appreciated. Thanks! – Hyder Sep 30 '19 at 05:25
1

Found the solution. Updated my callbacks to the following :

__weak typeof(self) weakSelf = self;

    qtyStepper.incrementCallback = ^(PKYStepper *stepper, float newValue) {

        CartViewController *sSelf = weakSelf;

        [sSelf updateTotalCharges]; //Had to use WEAKSELF in the callback!

    };
Hyder
  • 1,163
  • 2
  • 13
  • 37