0

I have a navigation controller, which loads a UITableviewcontroller (DOArticleListViewController):

- (void) showList: (NSFetchedResultsController*) list title:(NSString*) title {
    DOArticleListViewController* listView = [[[self navigationController] storyboard] instantiateViewControllerWithIdentifier:@"DOArticleListViewController"];
    [listView setObjects:list];
    [listView setViewTitle:title];
    [[self navigationController] pushViewController:listView animated:YES];
}

When I tap the 'Back' button in the DOArticleListViewController the view is not released (no dealloc/viewDidUnload), and the memory usage increases every time I go back and forward.

What can be the reason, or how can I force it to release? I might have something to do with the "NSFetchedResultsController", as I only recently moved to ARC.

The declaration of the TableViewController is:

@interface DOPrototypeListViewController : DOPrototypeViewController <NSFetchedResultsControllerDelegate, UITableViewDelegate> {

    IBOutlet UITableView * _tableView;

    int _cellHeight;

@protected
    NSFetchedResultsController* _objects;   
    NSString* _cellIdentifier;

    bool _commonId;
    int _sectionItemsSkipped;
}

@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) NSFetchedResultsController* objects;

- (NSIndexPath*)calculateObjectIndexPath:(NSIndexPath*) indexPath;
- (NSIndexPath*)calculateTableIndexPath:(NSIndexPath*) indexPath;

@end

I declared the list as strong, as if I make it weak, the NSFetchedResultsController is unloaded when I am looking for the objects when going to the subsequent detailViewController.

EDIT: I think I might have a more fundamental problem, as profiling it seems no objects are ever released. Even if the retain count is 0, the object seems to stay in memory. I moved to ARC during the summer, and did an automatic conversion. I just wonder if I have a simple fundamental flaw somewhere which causes objects to be retained and never released/dealloc.

Do objects which are instantiated in the class itself to be set to nil? e.g. do I need to set this to nil:

_mediaPlayerHelper = [[DOMediaPlayerHelper alloc] init:self];

Before ARC I would have done that, but now I have no function which is called when a view controller is removed form the view-stack (and can be removed, but this is only when going back up a level, not when gong to a detail view controller).

Luuk D. Jansen
  • 4,402
  • 8
  • 47
  • 90
  • may need to be weak, yes. I think you are encountering a retain cycle issue there. Use the Instruments, with the Allocations tool to spot those – Dani Pralea Nov 14 '13 at 19:29
  • are you registering any observers or running any timers in the `DOArticleListViewController`? – Tobi Nov 14 '13 at 19:34
  • If I make the NSFetchedResultsController weak I lose the objects for the detailviewcontroller. I don't have any observers apart that the class is the delegate for the tableView. I could put objects on 'nil' if there is a function which is called only when the view controller is piped (not e.g. when a row is selected, so viewDidDisappear will not work) – Luuk D. Jansen Nov 14 '13 at 20:32
  • Just checked instruments. Each new instance is alive, but how can I check the reason. They have a refcount of 1, but how can I check where this is coming from? – Luuk D. Jansen Nov 14 '13 at 20:42
  • Think there dis a more fundamental problem, see edit – Luuk D. Jansen Nov 14 '13 at 22:19

1 Answers1

0

I think you can make a property and a Lazy instantiation for the

DOArticleListViewController* listView

-(DOArticleListViewController*)listView{
    if (!_listView){
        _list = [[[self navigationController] storyboard] instantiateViewControllerWithIdentifier:@"DOArticleListViewController"];
    }
    return _listView;
}

This way, you can reuse your VC.

Edited:

In response to the comment about the back button

// Set the left button for menu
UIImage *menuImage = [UIImage imageNamed:@"back_image"];

//create the button and assign the image
UIButton *menuButton = [UIButton buttonWithType:UIButtonTypeCustom];
[menuButton setImage:menuImage forState:UIControlStateNormal];

[menuButton addTarget:self action:@selector(backButtonEvent:) forControlEvents:UIControlEventTouchUpInside];

//create a UIBarButtonItem with the button as a custom view
UIBarButtonItem *menuBarItem = [[UIBarButtonItem alloc] initWithCustomView:menuButton];
self.navigationItem.leftBarButtonItem = menuBarItem;

Then on the backButtonEvent method you can add all the clean actions and then make the pop for the current VC:

-(IBAction)backButtonPressed:(id)sender{
    //Clear here
    [self.navigationController popViewControllerAnimated:YES];
}
Floydian
  • 249
  • 2
  • 17
  • That is a good idea, and I will consider for some classes. However, in some other view (menu) I sometimes have submenus so do need specific instances, and it doesn't help yet to determine what is causes the view not to be released. – Luuk D. Jansen Nov 14 '13 at 20:29
  • Yeah, you're right. Another thing you can do for this is overriding the back button with your own "back" method and cleaning all the strong references, observers and delegates before making the pop for the VC. – Floydian Nov 14 '13 at 20:46
  • Is there a specific build in function for that, or just by creating your own button and an action? – Luuk D. Jansen Nov 14 '13 at 20:49
  • Thanks, I might use that too. However, for the moment I have implemented the second answer in http://stackoverflow.com/questions/1816614/viewwilldisappear-determine-whether-view-controller-is-being-popped-or-is-showi – Luuk D. Jansen Nov 15 '13 at 16:35