0

I'm trying to finish an app but I'm having some memory leaks with CoreData when I delete the view from the navigation stack even though I released everything I created.

Basically the following method is called by the view below it.

+ (NSMutableArray *)getStoriesForSubscription:(Subscriptions *)s {
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *storiesEntity = [NSEntityDescription entityForName:@"Articles" inManagedObjectContext:ikub.context];
[request setEntity:storiesEntity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(belongsTo == %@)", s];
[request setPredicate:predicate];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"pubDate" ascending:NO selector:nil];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors]; 
NSError *error = nil;

NSMutableArray *stories = (NSMutableArray*)[ikub.context executeFetchRequest:request error:&error];
if (![ikub.context save:&error]) { NSLog(@"Cannot fetch the folders from the fetch request."); }
[sortDescriptors release];
[sortDescriptor release];
[request release];
return stories;
}


@implementation SubscriptionStories

@synthesize storiesTable, stories, subscription;

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [stories count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
  if (cell == nil) {
  cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cell"];
 }
 int index = [indexPath row];
 cell.textLabel.text   = [[stories objectAtIndex:index] title];
 cell.detailTextLabel.text = [[stories objectAtIndex:index] desc];
 cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;


 if ([[[stories objectAtIndex:index] read] isEqualToNumber:[NSNumber numberWithBool:NO]]) {
 cell.textLabel.textColor = [UIColor blackColor];
 } else {
 cell.textLabel.textColor = [UIColor grayColor];
 }

 return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
 StoryDetails *details = [[StoryDetails alloc] init];
 details.title = @"Detaje";
 details.t = [[stories objectAtIndex:[indexPath row]] title];
 details.d = [[stories objectAtIndex:[indexPath row]] desc];
 details.l = [[stories objectAtIndex:[indexPath row]] link];
 details.g = [[stories objectAtIndex:[indexPath row]] guid];
 details.p = (NSString *)[[stories objectAtIndex:[indexPath row]] pubDate];
 [SubscriptionsController setStoryAsRead:[[stories objectAtIndex:[indexPath row]] link] forSubscription:subscription];
 [self.navigationController pushViewController:details animated:YES];
 [details release];
}

- (void)viewDidLoad { 
[super viewDidLoad];
}

- (void)viewWillAppear:(BOOL)animated {
stories = [[SubscriptionsController getStoriesForSubscription:subscription] retain];
[storiesTable reloadData];
}

- (void)viewWillDisappear:(BOOL)animated { 
[stories release];
}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}

- (void)viewDidUnload {
[super viewDidUnload];
}

- (void)dealloc {
[subscription release];
[super dealloc];
}

Instruments says that the leak happens in this line:

stories = [[SubscriptionsController getStoriesForSubscription:subscription] retain];
SwiftArchitect
  • 47,376
  • 28
  • 140
  • 179
Olsi
  • 929
  • 2
  • 12
  • 26

3 Answers3

0

If you have declared the property stories with retain then the extra retain is not necessary.

self.stories = [SubscriptionsController getStoriesForSubscription:subscription];
AndersK
  • 35,813
  • 6
  • 60
  • 86
  • If I remove the retain, the app crashes when I get back to this view. – Olsi Jan 23 '11 at 13:32
  • I just added the self before stories, leaving the retain there and I get another kind of leak. This time in Foundation, -[NSArray(NSKeyValueSorting)] in the same row. :(((( – Olsi Jan 23 '11 at 13:35
  • there was nothing wrong with `stories = [[.. ] retain];` if you use `self.stories = [[..] retain];` with a retain property you have retained twice, which of course will leak. – Matthias Bauch Jan 23 '11 at 14:54
  • When I don't user self.stories there's a leak. When I use it, without reain the app crashes. – Olsi Jan 23 '11 at 15:12
0

my suggestions:

remove (another?) leak by changing your UITableViewCell creation to return an autoreleased cell

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    ...
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cell"] autorelease];
    ...
}

if that didn't help. (I had leaks were instruments was miles away from the actual leak). change your viewWillDisappear method to something like this

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [stories release];
    stories = nil;
}

and add another release for stories in dealloc

- (void)dealloc {
    [subscription release];
    [stories release];
    [super dealloc];
}

Maybe there are obscure ways that a dealloc happens without calling the viewWillDisappear: method.
I usually release everything in dealloc. As long as you make sure that you set an object to nil when you have released it in another method nothing bad will happen.

Matthias Bauch
  • 89,811
  • 20
  • 225
  • 247
0

The leak was in a totally different place. Instruments isn't always right.

Olsi
  • 929
  • 2
  • 12
  • 26