Not Able to Retrieve data using core data - iphone

I am using coredata in my application to store data.i have to add the data in one view controller and retrieve it in another view controller.i tried the following code but it is not working.
//addViewController.m
-(IBAction)save:(id)sender
{
CoreDataOneAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSManagedObject *newContact;
newContact = [NSEntityDescription insertNewObjectForEntityForName:#"Employee"
inManagedObjectContext:context];
[newContact setValue:name.text forKey:#"name"];
[newContact setValue:amount.text forKey:#"amount"];
name.text = #"";
amount.text = #"";
//label
status.text = #"saved";
NSError *error;
[context save:&error];
}
I want to retrieve the values and display them in a tableView
//retrieveViewController.m
- (void)viewDidLoad
{
objects = [[NSArray alloc]init];
CoreDataOneAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSEntityDescription *entityDesc = [NSEntityDescription entityForName:#"Employee"
inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDesc];
NSError *error;
objects = [context executeFetchRequest:request
error:&error];
[request release];
[super viewDidLoad];
}
//tableView
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [objects count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
labelOne = [[UILabel alloc]initWithFrame:CGRectMake(5, 11, 110, 21)];
labelTwo = [[UILabel alloc]initWithFrame:CGRectMake(230, 11, 70, 21)];
static NSString *cellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:cellIdentifier]autorelease];
}
[cell.contentView addSubview:labelTwo];
[cell.contentView addSubview:labelOne];
NSManagedObject *matches = nil;
matches = [objects objectAtIndex:indexPath.row];
NSString *str1=[NSString stringWithFormat:#"%#",[matches valueForKey:#"name"]];
labelOne.text = str1;
NSString *str2=[NSString stringWithFormat:#"%#",[matches valueForKey:#"amount"]];
labelTwo.text = str2;
return cell;
}
I am getting EXC_BAD_ACCESS error.i tried using NSZombieEnabled and i got the following error.
2012-04-27 11:59:18.153 CoreDataOne[4370:207] *** -[_PFArray objectAtIndex:]: message sent to deallocated instance 0x5931e40
i am able to retrieve the values if write the code what i have written in viewDidLoad in cellForRowAtIndexPath but how to declare the numberOfRows.

It looks like you are not using ARC. I think you need to retain the result of your fetch request in viewDidLoad (don't forget to release it in dealloc). Also, you are leaking by alloc/initing an array and then overwriting it.

Store the values in MutableArray in view didload where you are retrieving values. And then use it in your table view. Declare the noof Rows as array count.

Related

Weird Header Error when using NSFetchedResultsController

Since I can't really describe this error, I recorded my screen with the error.
http://www.youtube.com/watch?v=w2FqKKcL2Ck&feature=youtu.be
Basically I am not sure what to do. When the user finishes all the tasks in the Tasks To Complete section, I would like the section header to remain there...just with no objects in it (simply because its needed in order to add more tasks).
Luckily when the user doesn't have any Completed Tasks, the header there disappears which is what should happen. I would like the top header to not disappear though...
Also, same thing with the delete. I don't really want the Tasks To Complete section to disappear completely when the last object is deleted.
I've heard this is not possible unless you use a custom subclass like TAFetchResultsController, but I tried using that and it was just too complex for me to implement (and kind of broke my application rather than fix it). Maybe you guys have some suggestions?
Here is some relevant code:
Tasks core data properties
#interface Tasks : NSManagedObject
#property (nonatomic, retain) NSString *sectionString;
#end
#implementation Tasks
#dynamic sectionString;
#end
adding tasks to different sections
NSManagedObjectContext *context = self.managedObjectContext;
NSManagedObject *startingTask = [NSEntityDescription insertNewObjectForEntityForName:#"Tasks" inManagedObjectContext:context];
[startingTask setValue:#"Eat Dinner" forKey:#"taskName"];
[startingTask setValue:[NSNumber numberWithDouble:400] forKey:#"timeInterval"];
[startingTask setValue:#"Tasks To Complete" forKey:#"sectionString"];
NSManagedObject *finishedTask = [NSEntityDescription insertNewObjectForEntityForName:#"Tasks" inManagedObjectContext:context];
[finishedTask setValue:#"Do Laundry" forKey:#"taskName"];
[finishedTask setValue:[NSNumber numberWithDouble:400] forKey:#"timeInterval"];
[finishedTask setValue:#"Completed Tasks" forKey:#"sectionString"];
NSError *error;
if (![context save:&error]) {
NSLog(#"couldn't save: %#", [error localizedDescription]);
}
TableViewController.m:
-(void) viewDidLoad{
// ---Start Core Data With NSFetchedResultsController---
[super viewDidLoad];
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]){
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1);
}
// ---End Core Data w/ NSFetchedResultsController---
[self.tableView setDelegate:self];
[self setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
holdViewsArray = [[NSMutableArray alloc]init];
UIView *seperatorView;
UIView *seperatorView2;
NSString *sectionTitle = #"Tasks To Complete";
NSString *section2Title = #"Completed Tasks";
UILabel *label = [[UILabel alloc]init];
UILabel *label2 = [[UILabel alloc]init];
label.frame = CGRectMake(10.0, 5.0, 320.0, 50.0);
label.text = sectionTitle;
label2.frame = CGRectMake(10.0, 0.0, 320.0, 40.0);
label2.text = section2Title;
headerView = [[UIView alloc]initWithFrame:label.frame];
headerView2 = [[UIView alloc]initWithFrame:label2.frame];
CGRect sepFrame = CGRectMake(0, headerView.frame.size.height-2, 320, 1);
CGRect sep2Frame =CGRectMake(0, headerView2.frame.size.height-2, 320, 1);
seperatorView = [[UIView alloc] initWithFrame:sepFrame];
seperatorView2 = [[UIView alloc]initWithFrame:sep2Frame];
[headerView addSubview:seperatorView];
[headerView2 addSubview:seperatorView2];
[headerView addSubview:label];
[headerView addSubview:button];
[headerView2 addSubview:label2];
[holdViewsArray addObject:headerView];
[holdViewsArray addObject:headerView2];
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"Tasks" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *isCompleted = [[NSSortDescriptor alloc]initWithKey:#"sectionString" ascending:NO];
NSSortDescriptor *sort = [[NSSortDescriptor alloc]
initWithKey:#"dateCreated" ascending:YES];
[fetchRequest setSortDescriptors:#[isCompleted, sort]];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext sectionNameKeyPath:#"sectionString"
cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}-(void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
Tasks *task = [_fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = task.taskName.uppercaseString;
cell.detailTextLabel.text = [NSString stringWithFormat:#"%.0f", task.timeInterval];
cell.imageView.image = [UIImage imageNamed:#"unchecked.png"];
cell.imageView.highlightedImage = [UIImage imageNamed:#"uncheckedhighlighted.png"];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
if (indexPath.section == 1)
[cell.contentView setAlpha:0.5];
else {
[cell.contentView setAlpha:1];
}
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(handlechecking:)];
[cell.imageView addGestureRecognizer:tap];
cell.imageView.userInteractionEnabled = YES;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
cellSubclassCell *cell = [tableView dequeueReusableCellWithIdentifier:#"UITableViewCell"];
if (!cell)
cell = [[cellSubclassCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"UITableViewCell"];
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
-(void)handlechecking:(UITapGestureRecognizer *)t{
CGPoint tapLocation = [t locationInView:self.tableView];
NSIndexPath *tappedIndexPath = [self.tableView indexPathForRowAtPoint:tapLocation];
Tasks *task = [_fetchedResultsController objectAtIndexPath:tappedIndexPath];
if ([task.sectionString isEqual: #"Tasks To Complete"]){
task.sectionString = #"Completed Tasks";
} else if ([task.sectionString isEqualToString:#"Completed Tasks"]){
task.sectionString = #"Tasks To Complete";
}
[self.tableView reloadData];
NSTimeInterval time = [[NSDate date] timeIntervalSinceReferenceDate];
[task setDateCreated:time];
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
switch (section) {
case 0:
return [holdViewsArray objectAtIndex:0];
break;
case 1:
return [holdViewsArray objectAtIndex:1];
break;
}
return 0;
}
NSFetchedResultsController infers sections from the objects returned by the fetch. So if the number of items a section goes to zero, the section vanishes. That's just how NSFetchedResultsController works.
Your simplest option is probably a 3rd-party framework. Take a look at TLIndexPathTools. It provides an alternative to NSFetchedResultsController that does not require Core Data or an NSFetchRequest, meaning you can use it in more scenarios. Take a look at some of the example projects (the Core Data one is called "Core Data")- some cool things are done with few lines of code.
TLIndexPathTools supports empty sections, but not explicitly in the way you need. However, you can accomplish it with a few lines of code by overriding TLIndexPathController. The code would look something like this:
#interface MyIndexPathController : TLIndexPathController
#end
#import "MyIndexPathController.h"
#implementation MyIndexPathController
- (void)setDataModel:(TLIndexPathDataModel *)dataModel
{
if ([dataModel sectionForSectionName:#"MyFirstSectionName"] == NSNotFound) {
TLIndexPathSectionInfo *firstSection = [[TLIndexPathSectionInfo alloc] initWithItems:nil andName:#"MyFirstSectionName"];
NSMutableArray *sectionInfos = [NSMutableArray arrayWithArray:dataModel.sections];
[sectionInfos insertObject:firstSection atIndex:0];
dataModel = [[TLIndexPathDataModel alloc] initWithSectionInfos:sectionInfos andIdentifierKeyPath:dataModel.identifierKeyPath andCellIdentifierKeyPath:dataModel.cellIdentifierKeyPath];
}
super.dataModel = dataModel;
}
#end
What is happening here is we intercept the data model generated by the controller (based on the results of our fetch request) and check if the section of interest is present. If not, we create an empty section info object and combine it with the other section infos into a new data model and pass it along to the super class.
It should not be too difficult to extend generically to work with any set of required sections if needed.

self performSelector:#selector(loadData) withObject:nil - not working

I use:
self performSelector:#selector(loadData) withObject:nil...
it look like working with some command only in "loadData" but the rest are not.
Here is my viewdidload:
- (void)viewDidLoad
{
[super viewDidLoad];
[mActivity startAnimating];
[self performSelector:#selector(loadData) withObject:nil afterDelay:2];
//[mActivity stopAnimating];
}
and here is loadData:
-(void)loadData
{
[mActivity startAnimating];
NSLog(#"Start LoadData");
AppDelegate *delegate=(AppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *selectData=[NSString stringWithFormat:#"select * from k_proverb ORDER BY RANDOM()"];
qlite3_stmt *statement;
if(sqlite3_prepare_v2(delegate.db,[selectData UTF8String], -1,&statement,nil)==SQLITE_OK){
NSMutableArray *Alldes_str = [[NSMutableArray alloc] init];
NSMutableArray *Alldes_strAnswer = [[NSMutableArray alloc] init];
while(sqlite3_step(statement)==SQLITE_ROW)
{
NSString *des_strChk= [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement,3)];
if ([des_strChk isEqualToString:#"1"]){
NSString *des_str= [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement,4)];
[Alldes_str addObject:des_str];
}
}
Alldes_array = Alldes_str;
Alldes_arrayAnswer = Alldes_strAnswer;
}else{
NSLog(#"ERROR '%s'",sqlite3_errmsg(delegate.db));
}
listOfItems = [[NSMutableArray alloc] init];
NSDictionary *desc = [NSDictionary dictionaryWithObject:
Alldes_array forKey:#"description"];
[listOfItems addObject:desc];
//[mActivity stopAnimating];
NSLog(#"Finish loaData");}
it give me only printing 2 line, but did not load my Data to the table, but if I copy all the code from inside "loadData" and past in "viewDidLoad", it load the data to the table.
Any advice or help please.
A few things: If you see any NSLog output at all, then the performSelector is succeeding. You should change the title of your question.
If you are trying to load data into a table, the method should end with telling the UITableView to reloadData (or a more elaborate load using begin/end updates).
If the listOfItems is the data supporting the table, get this working first by hard-coding something like this:
-(void)loadData {
listOfItems = [NSArray arrayWithObjects:#"test1", #"test2", nil];
[self.tableView reloadData];
return;
// keep all of the code you wrote here. it won't run until you remove the return
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSString *string = [listOfItems objectAtIndex:indexPath.row];
cell.textLabel.text = string;
return cell;
// keep all of the code you probably wrote for this method here.
// as above, get this simple thing running first, then move forward
}
Good luck!

core data search issue iOS 5

Using core data, data is being fetched properly and shown properly, issue is with the search that it does not filter the results, whatever I type in the search bar, it does show the same table view with same data in the filtered results..
- (void)viewDidLoad
{
[super viewDidLoad];
if (context == nil)
{
context = [(VektorAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
app = [[UIApplication sharedApplication] delegate];
[self getData];
// create a filtered list that will contain products for the search results table.
filteredListItems = [[NSMutableArray alloc] initWithCapacity:[self.plateNumbers count]];
// restore search settings if they were saved in didReceiveMemoryWarning.
if (self.savedSearchTerm){
[self.searchDisplayController setActive:self.searchWasActive];
[self.searchDisplayController.searchBar setSelectedScopeButtonIndex:self.savedScopeButtonIndex];
[self.searchDisplayController.searchBar setText:savedSearchTerm];
self.savedSearchTerm = nil;
}
}
Fetching data from core data:
-(void)getData {
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Favouritesdata" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setFetchBatchSize:20];
[request setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"licenseplate" ascending:NO];
NSArray *newArray = [[NSArray alloc]initWithObjects:sort, nil];
[request setSortDescriptors:newArray];
NSLog(#"newArray: %#", newArray);
NSError *error;
results = [[context executeFetchRequest:request error:&error] mutableCopy];
plateNumbers = [results valueForKey:#"licenseplate"];
NSLog(#"plateNumbers: %#", plateNumbers);
[self setLicensePlateArray:results];
[self.favouritesTable reloadData];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == favouritesTable) {
return [licensePlateArray count];
} else { // handle search results table view
return [filteredListItems count];
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == favouritesTable) {
cellValue = [licensePlateArray objectAtIndex:indexPath.row];
} else { // handle search results table view
cellValue = [filteredListItems objectAtIndex:indexPath.row];
}
static NSString *CellIdentifier = #"vlCell";
VehicleListCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSLog(#"Cell Created");
NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:#"VehicleListCell" owner:nil options:nil];
for (id currentObject in nibObjects) {
if ([currentObject isKindOfClass:[VehicleListCell class]]) {
cell = (VehicleListCell *)currentObject;
}
}
NSInteger cellVal = indexPath.row;
NSLog(#"indexPath.row: %i", cellVal);
UILongPressGestureRecognizer *pressRecongnizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(tableCellPressed:)];
pressRecongnizer.delegate = self;
pressRecongnizer.minimumPressDuration = 0.5f;
[cell addGestureRecognizer:pressRecongnizer];
[pressRecongnizer release];
}
cell.textLabel.font = [UIFont systemFontOfSize:10];
Favouritesdata *favdata = [results objectAtIndex:indexPath.row];
cell.licPlate.text = [favdata licenseplate];
NSLog(#"cellvalue for cellforRow: %#", cell.licPlate.text);
return cell;
}
Search bar implementation:
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"SELF contains[cd] %#",
searchText];
self.filteredListItems = [self.plateNumbers filteredArrayUsingPredicate:resultPredicate];
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
/* [self filterContentForSearchText:searchString scope:
[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
*/
if ([[searchString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length])
self.favouritesTable = controller.searchResultsTableView;
return YES;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
[self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope:
[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];
return YES;
}
How to resolve this issue ?
Just make code clear before and define every methods, you are just setting predicate, not firing query for it.
just make separate method and just pass search text as parameter to that method for predicate and fire fetch query then reload table.

Error when populating table view with coredata

I am working with coredata and successfully saved the data in data storage but when I try to output what I stored using table view ,I am not able to do it.
Here the user will enter and click save ..so when he goes back..I want the table to populated with what name he or she has entered.
So I wrote the below code for saving and find data:
- (void) saveData
{
coredata123AppDelegate *appDelegate =
[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context =
[appDelegate managedObjectContext];
Contacts *newContact;
newContact = [NSEntityDescription
insertNewObjectForEntityForName:#"Contacts"
inManagedObjectContext:context];
[newContact setValue:name.text forKey:#"name"];
[newContact setValue:address.text forKey:#"address"];
[newContact setValue:phone.text forKey:#"phone"];
name.text = #"";
address.text = #"";
phone.text = #"";
NSError *error;
[context save:&error];
status.text = #"Contact saved";
}
- (void) findContact
{
coredata123AppDelegate *appDelegate =
[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context =
[appDelegate managedObjectContext];
NSEntityDescription *entityDesc =
[NSEntityDescription entityForName:#"Contacts"
inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDesc];
NSPredicate *pred =
[NSPredicate predicateWithFormat:#"(name = %#)",
name.text];
[request setPredicate:pred];
NSManagedObject *matches = nil;
NSError *error;
NSArray *objects = [context executeFetchRequest:request
error:&error];
for(Contacts *info in objects)
{
NSLog(#"Name:%#",info.name);
NSLog(#"Address:%#",info.address);
}
if ([objects count] == 0) {
status.text = #"No matches";
} else {
matches = [objects objectAtIndex:0];
address.text = [matches valueForKey:#"address"];
phone.text = [matches valueForKey:#"phone"];
status.text = [NSString stringWithFormat:
#"%d matches found", [objects count]];
}
[request release];
}
And to populate the table view i have written this code..
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"Contacts" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSError *error;
self.contacts = [context executeFetchRequest:fetchRequest error:&error];
[fetchRequest release];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
Contacts *info =[contacts objectAtIndex:indexPath.row];
cell.textLabel.text =info.name;
cell.detailTextLabel.text=info.address;
// Configure the cell...
return cell;
}
Are you getting proper number of elements in this objects array?
NSArray *objects = [context executeFetchRequest:request
error:&error];
if not, try changing the predicate with,
[NSPredicate predicateWithFormat:#"name=%#", name.text];
Otherwise, your code seems correct to me.

CoreData leaks when view is destroyed

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];
If you have declared the property stories with retain then the extra retain is not necessary.
self.stories = [SubscriptionsController getStoriesForSubscription:subscription];
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.
The leak was in a totally different place. Instruments isn't always right.