core data search issue iOS 5 - iphone

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.

Related

table cell showing up in wrong section in table view

DataModel.h code file
#import "DataModel.h"
#import <CoreData/CoreData.h>
#import "SettingsEntity.h"
#import "Constants.h"
#implementation DataModel
NSManagedObjectContext *managedObjectContextEntity;
NSManagedObjectContext *managedObjectContextMessage;
NSManagedObjectModel *managedObjectModel;
NSPersistentStoreCoordinator *persistentStoreCoordinator;
NSEntityDescription *theSettingsEntity;
NSEntityDescription *theMessagesEntity;
-(id) init
{
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"SOW" withExtension:#"momd"];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
NSError *error = nil;
NSURL *storeURL = [[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject] URLByAppendingPathComponent:[Constants SQLLiteDB]];
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:managedObjectModel];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
if (persistentStoreCoordinator != nil) {
managedObjectContextEntity = [[NSManagedObjectContext alloc] init];
[managedObjectContextEntity setPersistentStoreCoordinator:persistentStoreCoordinator];
managedObjectContextMessage = [[NSManagedObjectContext alloc] init];
[managedObjectContextMessage setPersistentStoreCoordinator:persistentStoreCoordinator];
}
theSettingsEntity = [NSEntityDescription entityForName:#"SettingsEntity" inManagedObjectContext:managedObjectContextEntity];
theMessagesEntity = [NSEntityDescription entityForName:#"MessageEntity" inManagedObjectContext:managedObjectContextMessage];
return self;
}
-(void) SaveSetting: (SettingsEntity *)setting
{
NSError *error = nil;
if (managedObjectContextEntity != nil) {
if ([managedObjectContextEntity hasChanges] && ![managedObjectContextEntity save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Confirmation" message:#"Settings were saved successfully." delegate:nil cancelButtonTitle:#"Okay" otherButtonTitles:nil, nil];
[alert show];
}
}
}
-(void) SaveMessage: (MessageEntity *)message
{
NSError *error = nil;
if (managedObjectContextMessage != nil) {
if ([managedObjectContextMessage hasChanges] && ![managedObjectContextMessage save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
}
-(NSArray *) GetSettingsResult
{
NSManagedObjectContext *context = managedObjectContextEntity;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:theSettingsEntity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"enteredDateTime" ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
NSArray *results = [context executeFetchRequest:request error:nil];
return results;
}
-(SettingsEntity *) GetSettingsEntity
{
SettingsEntity *settingsEntity = [NSEntityDescription
insertNewObjectForEntityForName:[theSettingsEntity name]
inManagedObjectContext:managedObjectContextEntity];
return settingsEntity;
}
-(NSArray *) GetMessageResult
{
NSFetchRequest *request = [self GetMessageFetchRequest];
NSArray *results = [managedObjectContextMessage executeFetchRequest:request error:nil];
return results;
}
-(NSFetchRequest *) GetMessageFetchRequest
{
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:theMessagesEntity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"sentDateTime" ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
return request;
}
-(NSFetchedResultsController *) GetMessageFetchResultsController
{
NSFetchRequest *fetchRequest = [self GetMessageFetchRequest];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContextMessage sectionNameKeyPath:#"typeMessage" cacheName:nil];
return aFetchedResultsController;
}
-(MessageEntity *) GetMessageEntity
{
MessageEntity *mEntity = [NSEntityDescription
insertNewObjectForEntityForName:[theMessagesEntity name]
inManagedObjectContext:managedObjectContextMessage];
return mEntity;
}
#end
HistoryTableView code file is as follows:
#import "HistoryTableViewController.h"
#import "MessageEntity.h"
#import "DataModel.h"
#import "HistoryDetailViewController.h"
#import "Constants.h"
#interface HistoryTableViewController ()
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;
#end
#implementation HistoryTableViewController
//todo: zulfiqar review this line of code.
#synthesize fetchedResultsController = __fetchedResultsController;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)awakeFromNib
{
[super awakeFromNib];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.rightBarButtonItem = self.editButtonItem;
//todo: get fetched controller here.. and reuse it every where in rest of this class.
}
/* faisal code starts here */
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSFetchedResultsController *c = [self fetchedResultsController];
NSArray *titles = [c sectionIndexTitles];
NSString *title = titles[section];
if ([title isEqualToString:#"E"])
{
return [Constants Email];
}
else if([title isEqualToString:#"T"])
{
return [Constants Text];
}
else
{
return [Constants Call];
}
}
- (NSArray *)sectionIndexTitlesForTableView: (UITableView *)aTableView
{
NSFetchedResultsController *c = [self fetchedResultsController];
return [c sectionIndexTitles];
}
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSFetchedResultsController *c = [self fetchedResultsController];
id<NSFetchedResultsSectionInfo> sectionInfo = c.sections[section];
return sectionInfo.numberOfObjects;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
NSFetchedResultsController *c = [self fetchedResultsController];
return c.sections.count;
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *path = self.tableView.indexPathForSelectedRow;
HistoryDetailViewController *hdvc = segue.destinationViewController;
NSFetchedResultsController *c = [self fetchedResultsController];
MessageEntity *message = (MessageEntity *)[c objectAtIndexPath:path];
hdvc.currentMessageEntity = message;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
/*
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSFetchedResultsController *c = [self fetchedResultsController];
id <NSFetchedResultsSectionInfo> sectionInfo = c.sections[section];
return sectionInfo.numberOfObjects;
}
*/
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSFetchedResultsController *c = [self fetchedResultsController];
NSString *CellIdentifier = [NSString stringWithFormat:#"Cell"];// %d_%d",indexPath.section,indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
MessageEntity *message = (MessageEntity *)[c objectAtIndexPath:indexPath];
cell.textLabel.text = message.typeMessage;
return cell;
/*
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"EEE. MMM. dd, yyyy HH:mm"];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
NSFetchedResultsController *c = [self fetchedResultsController];
MessageEntity *message = (MessageEntity *)[c objectAtIndexPath:indexPath];
NSString *sentDateTime = [dateFormat stringFromDate:message.sentDateTime];
NSString *contactAdd;
NSLog(message.typeMessage);
if ([message.typeMessage isEqualToString:[Constants Email]])
{
contactAdd = message.toEmailAddress;
}
else
{
NSString *unformatted = message.toPhoneNumber;
NSArray *stringComponents = [NSArray arrayWithObjects:[unformatted substringWithRange:NSMakeRange(0, 3)],
[unformatted substringWithRange:NSMakeRange(3, 3)],
[unformatted substringWithRange:NSMakeRange(6, [unformatted length]-6)], nil];
contactAdd = [NSString stringWithFormat:#"(%#) %#-%#", [stringComponents objectAtIndex:0], [stringComponents objectAtIndex:1], [stringComponents objectAtIndex:2]];
}
NSString *header = [[NSString alloc] initWithFormat:#"%#",contactAdd];
NSString *detail = [[NSString alloc] initWithFormat:#"%# on %#", message.sentName, sentDateTime];
cell.detailTextLabel.text = detail;
cell.textLabel.text = header;
return cell;
*/
}
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSFetchedResultsController *c = [self fetchedResultsController];
NSManagedObject *object = [c objectAtIndexPath:indexPath];
NSManagedObjectContext *context = self.fetchedResultsController.managedObjectContext;
[context deleteObject:object];
NSError *error = nil;
if (![context save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// The table view should not be re-orderable.
return NO;
}
- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView reloadData];
}
- (NSFetchedResultsController *)fetchedResultsController
{
if (__fetchedResultsController != nil) {
return __fetchedResultsController;
}
DataModel *data = [[DataModel alloc]init];
NSFetchedResultsController *aFetchedResultsController = [data GetMessageFetchResultsController];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return __fetchedResultsController;
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
switch(type) {
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView endUpdates];
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
*/
}
#end
My history table view looks as follows:
**Q. Why Email and Call are getting into wrong section?**
If you set a sectionNameKeyPath for the fetched results controller, then you must also add a first sort descriptor to the fetch request that uses the same key (or a key that generates the same relative ordering).
So for sectionNameKeyPath:#"typeMessage" you should add one sort descriptor for the key "typeMessage":
NSSortDescriptor *sort1 = [[NSSortDescriptor alloc] initWithKey:#"typeMessage" ascending:YES];
NSSortDescriptor *sort2 = [[NSSortDescriptor alloc] initWithKey:#"sentDateTime" ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sort1, sort2, nil];
[request setSortDescriptors:sortDescriptors];

Dynamic Table view data source

Hi I am doing a app in which i use a Dynamic view table, Bit i have a problem with NSManged Objects, can any one find out whats going wrong.
find the code below for your reference.
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return ([self.controlSelections count]);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"plainCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
id controlOption = [self.controlSelections objectAtIndex:indexPath.row];
NSString *option = nil;
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
if ([controlOption isKindOfClass:[NSString class]])
{
option = (NSString *)controlOption;
cell.textLabel.text = option;
}
else if ([controlOption isKindOfClass:[NSDictionary class]])
{
NSDictionary *optionDict = (NSDictionary *)controlOption;
option = [optionDict valueForKey:self.listKey];
cell.textLabel.text = option;
}
else if ([controlOption isKindOfClass:[NSManagedObject class]])
{
NSManagedObject *context=[self NSManagedObject];
NSManagedObject *optionData = (NSManagedObject *)controlOption;
option = [optionData valueForKey:self.listKey];
cell.textLabel.text = option;
}
return cell;
}
the problem is in the following code it is not taking NSMangedObject:
else if ([controlOption isKindOfClass:[NSManagedObject class]])
{
NSManagedObject *context=[self NSManagedObject];
NSManagedObject *optionData = (NSManagedObject *)controlOption;
option = [optionData valueForKey:self.listKey];
cell.textLabel.text = option;
}
any help will be appreciated. thanks in advance.
import in Prefix.pch file
Try something on these lines -
else if ([controlOption isKindOfClass:[NSManagedObject class]])
{
NSManagedObjectContext *context=[self managedObjectContext]; //I guess you have MOC somewhere.
NSEntityDescription *entityDesc = [NSEntityDescription entityForName:[optionData valueForKey:self.listKey] inManagedObjectContext: context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDesc];
NSError *error;
NSArray *objects = [context executeFetchRequest:request error:&error];
cell.textLabel.text = [objects objectAtIndex:0]; //for eg
}

crashes in Xcode version 4.2 and iOS 5(released oct-12, 2011) at [self.tableview reload data]

i was implementing the table view programmatically, where i set property of mSelectedSubUnitIndex of (NSIndexPath) type as non atomic and retain and synthesized in .m . When i load my tableviewcontroller then method:
(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath
:(NSIndexPath *)indexPath
{
CGFloat height = 0.0;
SubUnit *subUnit = (SubUnit*)[mSubUnitsArray objectAtIndex:indexPath.row];
NSArray *subUnitExercises = [self sortArray:[subUnit.subUnitExercise allObjects]];
NSLog(#"mSelectedSubUnitIndex.row........%d",mSelectedSubUnitIndex.row);
NSLog(#"subUnitExercises........%d",[subUnitExercises count]);
if (indexPath.row == mSelectedSubUnitIndex.row && [subUnitExercises count]>1) {
height =CELL_EXPAND_HEIGHT ;
}
else {
height = CELL_NORMAL_HEIGHT;
}
return height;
}
run quite fine. When i return back to my tableviewcontoller from other controller then it crashes(object message send) at same method on line number 5 at NSLog, and give exception at method at [self.tableView reloadData];. It is resolved by commenting[self.tableView reloadData];.
-(void)viewDidAppear:(BOOL)animated
{
DebugLog(#"start");
//[self.tableview reloadData];
execountarray=[[NSMutableArray alloc]init];
for(int k=0;k<[mSubUnitsArray count];k++)
{
SubUnit *subUnit = (SubUnit*)[mSubUnitsArray objectAtIndex:k];
NSArray *subUnitExercises = [subUnit.subUnitExercise allObjects];
[execountarray addObject:[NSString stringWithFormat:#"%d",[subUnitExercises
count]]];
}
///////////////
if (managedObjectContext){
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"TSubUnitExerciseProgress" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
// Order the events by creation date, most recent first.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
initWithKey:#"editDate" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor,
nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptor release];
[sortDescriptors release];
// Execute the fetch -- create a mutable copy of the result.
NSError *error = nil;
NSMutableArray *mutableFetchResults = [[managedObjectContext
executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil) {
// Handle the error.
myNotes = nil;
[myNotes removeAllObjects];
}
else
{
[myNotes setArray: mutableFetchResults];
}
//NSLog(#"My notes count:--------unitviewcontroller--------------->%d",
[myNotes count]);
if([myNotes count] ==0)
{
setExer1Done:NO;
setExer2Done:NO;
}
else
{
NSLog(#"hey :P");
}
}
// [self.tableview reloadData];
}
didSelectRowAtIndex
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
*)indexPath
{
DebugLog(#" -start- \n");
mSelectedSubUnitIndex = indexPath;
SubUnit *subUnit = (SubUnit*)[mSubUnitsArray objectAtIndex:indexPath.row];
NSArray *subUnitExercises = [self sortArray:[subUnit.subUnitExercise allObjects]];
if([subUnitExercises count]!=1)
{
NSArray* paths = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:
[mSelectedSubUnitIndex row] inSection:0]];
[tableview beginUpdates];
[tableview deleteRowsAtIndexPaths:paths
withRowAnimation:UITableViewRowAnimationFade];
[tableview insertRowsAtIndexPaths:paths
withRowAnimation:UITableViewRowAnimationFade];
[tableview endUpdates];
}
else
{
//SubUnit *subUnit = (SubUnit*)[mSubUnitsArray objectAtIndex:
[mSelectedSubUnitIndex row]];
SubUnit *subUnit = (SubUnit*)[mSubUnitsArray objectAtIndex:indexPath.row];
NSArray *subUnitExercises = [self sortArray:[subUnit.subUnitExercise
allObjects]];
if ([subUnitExercises count] > 0) {
SubUnitExercise *subUnitExercise = [subUnitExercises
objectAtIndex:0];
[self loadSubUnitExercise:subUnitExercise];
}
}
}
this is running on iOS 4 but when i build through Xcode version 4.2 and iOS 5 (released oct-12, 2011) then it crashes. Can't figure out the problem. help me out!!
cellForRowAtIndex method
now i am getting exception at if-statement at mSelectedsubunitindex.row when i scroll, but i resolved only checking that if (indexPath.row){}, and also row remain selected when i return bad to my tableview controller
- (void)tableView:(UITableView *)tableView willDisplayCell:
(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
DebugLog(#"-start- \n");
SubUnit *subUnit = (SubUnit*)[mSubUnitsArray objectAtIndex:indexPath.row];
NSArray *subUnitExercises = [self sortArray:[subUnit.subUnitExercise allObjects]];
NSString *str1 = [[subUnit performSelector:#selector(title)]copy];
if ([str1 isEqualToString:#"1. was/were"])
{
global = str1;
}
//if(indexPath.row==mSelectedSubUnitIndex.row)
if(indexPath.row)
{
if ([subUnitExercises count] != 1)
{
SubUnit *subUnit = (SubUnit*)[mSubUnitsArray objectAtIndex:
[mSelectedSubUnitIndex row]];
NSArray *subUnitExercises = [self sortArray:
[subUnit.subUnitExercise allObjects]];
SubUnitCell *subUnitcell = (SubUnitCell*) cell;
mCellSubTopicLabel.text = subUnit.title;
if([myNotes count] == 0)
{
NSNumber *isDone = [[subUnitExercises objectAtIndex:1] isDone];
[subUnitcell setExer2Done:NO];
mExer2Checkbox.image = [UIImage imageNamed:[isDone boolValue]?
kExerciseCheckmark :kExerciseWrongmark];
isDone = [[subUnitExercises objectAtIndex:0] isDone];
[subUnitcell setExer1Done:NO];
mExer1Checkbox.image = [UIImage imageNamed:[isDone boolValue]?
kExerciseCheckmark :kExerciseWrongmark];
}
else
{
NSNumber *isDone = [[subUnitExercises objectAtIndex:1] isDone];
[subUnitcell setExer2Done:[isDone boolValue]];
mExer2Checkbox.image = [UIImage imageNamed:[isDone boolValue]?
kExerciseCheckmark :kExerciseWrongmark];
isDone = [[subUnitExercises objectAtIndex:0] isDone];
[subUnitcell setExer1Done:[isDone boolValue]];
mExer1Checkbox.image = [UIImage imageNamed:[isDone boolValue]?
kExerciseCheckmark :kExerciseWrongmark];
}
[subUnitcell.contentView addSubview:mCellSubTopicContentView];
}
}
For some reason NSIndexPath assignment (=) and equality(==) is not working in IOS5. I have solved the problem using self before any NSIndexPath object e.g.
self.mSelectedSubUnitIndex
There is another way solving this assignment using copy like this:
anIndexPath = (NSIndexPath*) [anotherIndexPath copy];
Equality works in same way. Like:
if([self.mSelectedSubUnitIndex isEqual:anotherIndexPath])
{
}
Just had a quick once over of your code. Two things jump out at me:
1: The very last line of your tableView:cellForRowAtIndexPath: calls [self.tableview reloadData].
This is unnecessary as the returned cell will be displayed as you have just configured it. It would also seem that this would cause a drawing loop ("reloadData->cellForRowAtIndexPath->reloadData->cellForRowAtIndexPath-> etc..). Try removing this line and see if this fixes your problems.
2: You don't seem to be re-using cells although one of your comments seemt to imply that you think you are. I would expect the beginning of the method to start similar to the code below:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
/* Load a custom cell from a NIB
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellNib owner:self options:nil];
cell = (UITableViewCell *)[nib objectAtIndex:0];
*/
// Assume SubUnitCell exists somewhere
SubUnitCell *cell = [[[SubUnitCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Retrieve config data and configure the cell as required in the code below - real config code needs to be added
NSNumber *isDone = [NSNumber numberWithBool:NO];
SubUnit *subUnit = (SubUnit*)[mSubUnitsArray objectAtIndex:[indexPath row]];
[cell setTitle:subUnit.title];
if([myNotes count] ==0)
{
[cell setExer1Done:NO];
[cell setExer2Done:NO];
}
else
{
NSLog(#"My notes count:--------unitviewcontroller----->%d",[myNotes count]);
}
// All your other configuration code
.......
.......
.......
return cell;
}
Also please try and post the symbolicated crash log so people can see the exact error and path to the error.

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.

Objective-C woes: cellForRowAtIndexPath crashes

I want to the user to be able to search for a record in a DB. The fetch and the results returned work perfectly. I am having a hard time setting the UItableview to display the result tho. The application continually crashes at cellForRowAtIndexPath. Please, someone help before I have a heart attack over here. Thank you.
#implementation SearchViewController
#synthesize mySearchBar;
#synthesize textToSearchFor;
#synthesize myGlobalSearchObject;
#synthesize results;
#synthesize tableView;
#synthesize tempString;
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
}
#pragma mark -
#pragma mark Table View
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//handle selection; push view
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
/* if(nullResulSearch == TRUE){
return 1;
}else {
return[results count];
}
*/
return[results count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1; // Test hack to display multiple rows.
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Search Cell Identifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil){
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:CellIdentifier] autorelease];
}
NSLog(#"TEMPSTRING %#", tempString);
cell.textLabel.text = tempString;
return cell;
}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
self.tableView = nil;
}
- (void)dealloc {
[results release];
[mySearchBar release];
[textToSearchFor release];
[myGlobalSearchObject release];
[super dealloc];
}
#pragma mark -
#pragma mark Search Function & Fetch Controller
- (NSManagedObject *)SearchDatabaseForText:(NSString *)passdTextToSearchFor{
NSManagedObject *searchObj;
UndergroundBaseballAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *managedObjectContext = appDelegate.managedObjectContext;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == [c]%#", passdTextToSearchFor];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Entry" inManagedObjectContext:managedObjectContext];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[request setEntity: entity];
[request setPredicate: predicate];
NSError *error;
results = [managedObjectContext executeFetchRequest:request error:&error];
if([results count] == 0){
NSLog(#"No results found");
searchObj = nil;
nullResulSearch == TRUE;
}else{
if ([[[results objectAtIndex:0] name] caseInsensitiveCompare:passdTextToSearchFor] == 0) {
NSLog(#"results %#", [[results objectAtIndex:0] name]);
searchObj = [results objectAtIndex:0];
nullResulSearch == FALSE;
}else{
NSLog(#"No results found");
searchObj = nil;
nullResulSearch == TRUE;
}
}
[tableView reloadData];
[request release];
[sortDescriptors release];
return searchObj;
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
textToSearchFor = mySearchBar.text;
NSLog(#"textToSearchFor: %#", textToSearchFor);
myGlobalSearchObject = [self SearchDatabaseForText:textToSearchFor];
NSLog(#"myGlobalSearchObject: %#", myGlobalSearchObject);
tempString = [myGlobalSearchObject valueForKey:#"name"];
NSLog(#"tempString: %#", tempString);
}
#end
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[UILongPressGestureRecognizer isEqualToString:]: unrecognized selector sent to instance 0x3d46c20'
The problem may be to do with reference counting.
in - (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar method, try either
self.tempString = [myGlobalSearchObject valueForKey:#"name"];
(assuming tempString is set to retain)
OR
tempString = [[myGlobalSearchObject valueForKey:#"name"] retain];
I would also advise doing some checking for nil values. i.e. what if [myGlobalSearchObject valueForKey:#"name"] == nil?