I've got a UITableView which is filled using a Core Data NSFetchedResultsController. I've now added a UISegmentedControl to the view and when you change the current segment, I'd like the contents of the tableview to change.
I've read around online that it would be wise to use two different NSFetchedResultsControllers as then I can benefit from the built-in caching. Only problem is I can't seem to find any sample code for doing this and don't know where to begin.
Can anyone explain where to begin in creating a second NSFetchedResultsController and changing which sources the tableview based on the segmented control?
View header code:
#import <CoreData/CoreData.h>
#interface DomainViewController : UIViewController <NSFetchedResultsControllerDelegate, UITableViewDataSource, UITableViewDelegate> {
UITableView *domainView;
UISegmentedControl *segmentedControl;
NSString *domain;
}
#property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;
#property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
#property (nonatomic, retain) NSString *domain;
#property (nonatomic, retain) IBOutlet UITableView *domainView;
#property (nonatomic, retain) IBOutlet UISegmentedControl *segmentedControl;
- (IBAction)segmentedControlIndexChanged;
View implementation code:
#interface DomainViewController ()
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;
#end
#implementation DomainViewController
#synthesize fetchedResultsController = __fetchedResultsController;
#synthesize managedObjectContext = __managedObjectContext;
#synthesize domain;
#synthesize domainView;
#synthesize segmentedControl;
- (void)viewDidLoad
{
[super viewDidLoad];
if (self.managedObjectContext == nil)
{
self.managedObjectContext = [(GARankingsAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
}
- (IBAction)segmentedControlIndexChanged
{
switch(self.segmentedControl.selectedSegmentIndex){
case 0:
break;
case 1:
break;
default:
break;
}
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = [[managedObject valueForKey:#"Keyphrase"] description];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (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];
}
// Configure the cell.
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (NSFetchedResultsController *)fetchedResultsController
{
if (__fetchedResultsController != nil)
{
return __fetchedResultsController;
}
/*
Set up the fetched results controller.
*/
// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Result" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"Keyphrase" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:#"Root"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
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. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
*/
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return __fetchedResultsController;
}
Any help is much appreciated. Thanks.
UPDATE: updated code
View header code:
#property (nonatomic, retain) NSFetchedResultsController *currentFetchedResultsController;
#property (nonatomic, retain) NSFetchedResultsController *competitorFetchedResultsController;
#property (nonatomic, retain) NSFetchedResultsController *keyphraseFetchedResultsController;
View implementation code:
#synthesize currentFetchedResultsController = __fetchedResultsController;
#synthesize competitorFetchedResultsController;
#synthesize keyphraseFetchedResultsController;
- (NSFetchedResultsController *)fetchedResultsController
{
if (__fetchedResultsController != nil)
{
return __fetchedResultsController;
}
/*
Set up the fetched results controller.
*/
// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Result" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"Keyphrase" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:#"Root"];
aFetchedResultsController.delegate = self;
//self.fetchedResultsController = aFetchedResultsController;
self.currentFetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
NSError *error = nil;
//if (![self.fetchedResultsController performFetch:&error])
if (![self.currentFetchedResultsController 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. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
*/
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return __fetchedResultsController;
}
You could add another instance variable that represents the currently selected NSFetchedResultsController. And when the UISegmentedControl changes update this ivar.
this could be the action that is triggered by the valuechange event of the segment
- (IBAction *)segmentChanged:(UISegmentedControl *)sender {
if ([sender selectedSegmentIndex] == 0) {
self.currentFetchedResultsController = self.nsfrc1;
[self.tableView reloadData];
}
else if ([sender selectedSegmentIndex] == 1) {
self.currentFetchedResultsController = self.nsfrc2;
[self.tableView reloadData];
}
}
one UITableViewDataSource method as example:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[self.currentFetchedResultsController sections] count];
}
and you have to make sure that only the current nsfrc triggers a tableview update in the NSFetchedResultsControllerDelegate methods. So you have to change all of them too.
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
if (controller == self.currentFetchedResultsController) {
[self.tableView beginUpdates];
}
}
EDIT: Nope, you are doing it wrong. the currentFetchedResultsController is just an ivar, without a lazy loading getter. It's "just" a pointer to the currently used controller.
But the two other fetchedResultsControllers should have such a lazy loading getter.
- (NSFetchedResultsController *)competitorFetchedResultsController {
if (!myCompetitorFetchedResultsController) {
// create competitorFetchedResultsController
}
return myCompetitorFetchedResultsController;
}
- (NSFetchedResultsController *)keyphraseFetchedResultsController {
if (!myKeyphraseFetchedResultsController) {
// create keyphraseFetchedResultsController
}
return myKeyphraseFetchedResultsController;
}
and then switch with:
self.currentFetchedResultsController = self.keyphraseFetchedResultsController;
or
self.currentFetchedResultsController = self.competitorFetchedResultsController;
Related
I have two tableViews, the main one adds the parent object, and when you click on a parent object in the tableView, it takes you to the child tableView, I did the first part successfully, but when it comes to fetching the "RIGHT" child objects I get confused, I way I do it is that I fetch ALL child object, the using enumeration I pick the right ones and put then into a NSSet, but that doesn't work, here's the child object table view.m:
#import "MinorGoalsTableViewController.h"
#interface MinorGoalsTableViewController ()
#end
#implementation MinorGoalsTableViewController
#synthesize selectedGoal = _selectedGoal;
#synthesize fetchedResultsController = _fetchedResultsController;
#synthesize minorGoalsSet;
// init with goal (for GTVC)
- (id) initWithGoal:(Goal *)goal {
if (self = [super init]) {
_selectedGoal = goal;
}
return self;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSError *error = nil;
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
NSLog(#"Minor Goals in %# are: %lu", self.selectedGoal.title , (unsigned long)[self.selectedGoal.minorGoal count]);
// self.minorGoalsSet = nil;
// initializing minorGoalsSet
self.minorGoalsSet = [[NSMutableSet alloc] init];
// performing fetch
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(#"Error fetching all minor goals: %#", error);
abort();
}
// creating NSSet that will carry all selectedGoal minor goals
NSSet *minorGoals = self.selectedGoal.minorGoal;
// creating a loop to add minor goals in minorGoalsSet
// add existing minor goals in selected goal to minorGoalsSet
for (MinorGoal *minor in minorGoals) {
[minorGoalsSet addObject:minor];
}
NSLog(#"minor goals in set: %lu", (unsigned long) [minorGoalsSet count]);
NSLog(#"minor goals in set2: %lu", (unsigned long) [minorGoals count]);
// setting nav title to selected goal title
self.navigationItem.title = _selectedGoal.title;
// adding "add" button to nav
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(addNewMinorGoal)];
}
- (void) viewWillDisappear:(BOOL)animated {
self.selectedGoal = nil;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.selectedGoal.minorGoal count];
// id <NSFetchedResultsSectionInfo> secInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
// return [secInfo numberOfObjects];
}
- (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];
}
cell.accessoryType = UITableViewCellAccessoryNone;
// Configure the cell...
MinorGoal *minor = [self.fetchedResultsController objectAtIndexPath:indexPath];
// well see about that later
if ([minorGoalsSet containsObject:minor]) {
cell.textLabel.text = minor.title;
}
// setting cell's title to minor goal's title
// cell.textLabel.text = minor.title;
return cell;
}
pragma mark - fetched results controller method
- (NSFetchedResultsController*) fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
// creating fetch request
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"MinorGoal"
inManagedObjectContext:self.selectedGoal.managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"title"
ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// setting _fetchedResultsController
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.selectedGoal.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
// performing fetch
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(#"Error fetching minors: %#", error);
}
// returning
return _fetchedResultsController;
}
pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
- (void) addNewMinorGoal {
// code to show UIAlertView that will add new minor goal
// creating UIAlertView
UIAlertView *addMinorGoalAlert = [[UIAlertView alloc] initWithTitle:#"Add Minor Goal" message:#"Minor Goal Title" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Save", nil];
// Adding plain textfield for minor goal title
addMinorGoalAlert.alertViewStyle = UIAlertViewStylePlainTextInput;
// showing UIAlertView
[addMinorGoalAlert show];
}
pragma mark - UIAlertView for Add New Minor Delegation
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
NSLog(#"Adding Minor Goal Canceled!");
}
else
{
// creating string will carry textField value
NSString *minorTitle = [[alertView textFieldAtIndex:0]text];
// creating new minor goal
MinorGoal *newMinorGoal = [NSEntityDescription
insertNewObjectForEntityForName:#"MinorGoal"
inManagedObjectContext:self.selectedGoal.managedObjectContext];
// setting title of new minor goal
newMinorGoal.title = minorTitle;
[self.selectedGoal addMinorGoalObject:newMinorGoal];
// saving
NSError *error = nil;
if (![self.selectedGoal.managedObjectContext save:&error]) {
NSLog(#"Error saving new minor goal: %#", error);
}
NSLog(#"we save %# to %# and theres %lu in it", newMinorGoal.title, self.selectedGoal.title, (unsigned long) [self.selectedGoal.minorGoal count]);
// fetching
[self.fetchedResultsController performFetch:&error];
// reloading tableView data
[self.tableView reloadData];
}
}
#end
Just tell me the right way to fetch the right child object, and should i put them in a NSSet?
It appears that you are using a NSFetchedResultsController to get ALL MinorGoal instances, but you just want to show the child MinorGoals. If you want to use an NSFetchedResultsController then you need to add a predicate to the fetch so that it only returns the MinorGoals that are children of the selected Goal. Assuming that you have created a relationship between MinorGoal and Goal called "parentGoal":
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"self.parentGoal = %#", self.selectedGoal];
Alternatively, don't us the NSFetchedResultsController and instead use the relationship. You will need to convert the NSSet to an array and sort it as the previous answer.
Store your parent object somewhere in your child view controller, typically it should be like
.h file:
#property (nonactomic, strong) ParentObject *parentObject;
.m file
- (id)initWithObject:(ParentObject *)parent {
…
_parentObject = parent;
…
}
then fetching:
(you should have #property (nonatomic, strong) NSFecthedResultsController *fetchedResultController)
- (NSFetchedResultsController*)fetchedResultController {
if (_fetchedResultController) {
return _fetchedResultController;
}
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:NSStringFromClass([ChildObject class])];
[request setEntity:entity];
NSSortDescriptor *sortDescription = [NSSortDescriptor sortDescriptorWithKey:#"sortOrder" ascending:YES];
[request setSortDescriptors:#[sortDescription]];
request.predicate = [NSPredicate predicateWithFormat:#"(parent == %#)", self.parentObject];
NSFetchedResultsController *controller = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:[NSManagedObjectContext mainThreadContext] sectionNameKeyPath:nil cacheName:nil];
controller.delegate = self;
_fetchedResultController = controller;
return _fetchedResultController;
}
then implement method
- (void)performFetch {
NSError *error = nil;
[self.fetchedResultController performFetch:&error];
if (![self.fetchedResultController performFetch:&error]) {
[self showAlertWithError:error];
}
else {
[self.tableView reloadData];
}
}
thats it basically you will receive all child objects you need sorted and filtered by predicate
seems like I was doing it the hard way, simply create new array that will hold the child objects.
NSMutableArray *minors = self.selectedGoal.minorGoals.allObjects.
and when you obtain change or add, do it two times, once to the array, and another time with the "self.selectedGoal.managedObjectContext".
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];
Hi i'm fairly new to xcode and i'm having trouble getting my head around why im getting this error "use of undeclared identifier" I'm basically trying to return fetched results to a table view.
// UNBSearchBooksViewController.m
#import "UNBSearchBooksViewController.h"
#import "NBAppDelegate.h"
#interface UNBSearchBooksViewController ()
#end
#implementation UNBSearchBooksViewController
#synthesize booksSearchBar;
#synthesize searchTableView;
#synthesize fetchedResultsController, managedObjectContext;
- (void)viewDidLoad
{
[super viewDidLoad];
// NSFetchRequest needed by the fetchedResultsController
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// NSSortDescriptor tells defines how to sort the fetched results
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"title" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// fetchRequest needs to know what entity to fetch
NSEntityDescription *entity = [NSEntityDescription entityForName:#"BookInfo" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:#"Root"];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [fetchedObjects count];
}
// Customize the appearance of table view cells.
- (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];
}
// Configure the cell "this is where my problem is" use of undeclared identifier
BookInfo *info = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = info.title;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
- (void) searchBarSearchButtonClicked:(UISearchBar *)theSearchBar
{
if (self.booksSearchBar.text !=nil)
{
NSPredicate *predicate =[NSPredicate predicateWithFormat:#"bookName contains[cd] %#", self.booksSearchBar.text];
[fetchedResultsController.fetchRequest setPredicate:predicate];
}
else
{
NSPredicate *predicate =[NSPredicate predicateWithFormat:#"All"];
[fetchedResultsController.fetchRequest setPredicate:predicate];
}
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error])
{
// Handle error
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1); // Fail
}
fetchedObjects = fetchedResultsController.fetchedObjects;
[booksSearchBar resignFirstResponder];
[searchTableView reloadData];
}
- (void) searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
searchBar.showsCancelButton = YES;
}
- (void) searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
searchBar.showsCancelButton = NO;
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
[searchBar resignFirstResponder];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
#end
Your problem is that you are assigning to a specific subclass the results typed as a base class. As you stated, this is where you get the warning:
BookInfo *info = [self.fetchedResultsController objectAtIndexPath:indexPath];
'NSFetchedResultsController' returns an object of type 'id' from
- (id)objectAtIndexPath:(NSIndexPath *)indexPath
(and I suppose it could return a NSManagedObject * too), but you assign it to a BookInfo object. Since there is a mismatch here, you need to cast the return value to what you know it is:
BookInfo *info = (BookInfo *)[self.fetchedResultsController objectAtIndexPath:indexPath];
and your warning will go away.
I have a huge problem with NSFetchedResultsCOntroller. I'm using fetchedResultsContrioller and I have interface with 3 tabs. They use Core Data too. But I have a problem with only ONE of them.
Faktura *faktura = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = faktura.NumerFV; // THE CRASH IS HERE
int productsCount = [faktura.Produkty count]; // OR HERE
NSString *kontrahentName = [faktura.Kontrahent valueForKey:#"NazwaKrotka"]; // OR HERE
cell.detailTextLabel.text = [NSString stringWithFormat:#"nabywca: %#, produktów: %d",kontrahentName, productsCount];
cell.imageView.image = [UIImage imageNamed:#"faktura_cell_image.png"];
cell.hidesImageWhileEditing = YES;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
Faktura is my NSManagedObject subclass.
NSZombie says:
-[CFDictionary retain]: message sent to deallocated instance 0x5d619d0
My fetchedResultsController implementation:
- (NSFetchedResultsController *)fetchedResultsController {
if (__fetchedResultsController != nil) return __fetchedResultsController;
// Setup the table
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Faktura" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Setup the sort descriptors
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"DataWystawienia" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Create the fetched results controller
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) { // THE CRASH IS HERE UNLESS I INIT NSFetchedResultsController WITH cacheName:nil. (IF IT'LL BE cacheName:#"Root" IT CRASHES.)
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Błąd Krytyczny" message:#"Wystąpił nieznany błąd przy zmienianiu zawartości w bazie danych. Dla dobra twoich danych prosimy niezwłocznie wyjść z aplikacji i spróbować ponownie." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return __fetchedResultsController;
}
Faktura.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#interface NSArrayToDataTransformer : NSValueTransformer #end
#interface NSDictionaryToDataTransformer : NSValueTransformer #end
#interface Faktura : NSManagedObject
#property (nonatomic, retain) NSDate * DataZaplaty;
#property (nonatomic, retain) NSString * NumerFV;
#property (nonatomic, retain) NSDate * DataWystawienia;
#property (nonatomic, retain) NSDate * DataSprzedazy;
#property (nonatomic, retain) id Produkty;
#property (nonatomic, retain) id Kontrahent;
#end
Faktura.m
#import "Faktura.h"
#implementation Faktura
#dynamic DataZaplaty;
#dynamic NumerFV;
#dynamic DataWystawienia;
#dynamic DataSprzedazy;
#dynamic Produkty;
#dynamic Kontrahent;
+ (void)initialize {
if (self == [Faktura class] ) {
NSArrayToDataTransformer *arrayTransformer = [[NSArrayToDataTransformer alloc] init];
[NSValueTransformer setValueTransformer:arrayTransformer forName:#"NSArrayToDataTransformer"];
NSDictionaryToDataTransformer *dictTransformer = [[NSDictionaryToDataTransformer alloc] init];
[NSValueTransformer setValueTransformer:dictTransformer forName:#"NSDictionaryToDataTransformer"];
}
}
#end
#implementation NSArrayToDataTransformer
+ (BOOL)allowsReverseTransformation {
return YES;
}
+ (Class)transformedValueClass {
return [NSData class];
}
- (id)transformedValue:(id)value {
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:value];
return data;
}
- (id)reverseTransformedValue:(id)value {
NSArray *array = [NSKeyedUnarchiver unarchiveObjectWithData:value];
return [array autorelease];
}
#end
#implementation NSDictionaryToDataTransformer
+ (BOOL)allowsReverseTransformation {
return YES;
}
+ (Class)transformedValueClass {
return [NSData class];
}
- (id)transformedValue:(id)value {
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:value];
return data;
}
- (id)reverseTransformedValue:(id)value {
NSDictionary *dict = [NSKeyedUnarchiver unarchiveObjectWithData:value];
return [dict autorelease];
}
#end
My Faktura object insertion code
- (void)fakturaCreator:(FakturaCreator *)form didEndWithValues:(NSDictionary *)values {
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
Faktura *newFaktura = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];
[newFaktura setNumerFV:[values valueForKey:#"id"]];
[newFaktura setDataWystawienia:[values valueForKey:#"creationDate"]];
[newFaktura setDataSprzedazy:[values valueForKey:#"sellDate"]];
[newFaktura setDataZaplaty:[values valueForKey:#"paymentDate"]];
[newFaktura setKontrahent:[values valueForKey:#"kontrahent"]];
[newFaktura setProdukty:[values valueForKey:#"produkty"]];
NSError *error = nil;
if (![context save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
[self.emptySectionView setHidden:YES];
}
FakturaCreator is my UIViewController where user create an invoice. values array contains dictionary of values: my invoice number (NSString), various dates (NSDate), client (NSDictionary) and products (NSArray).
Please help me!
If you want some additional code, i'll put it here.
EDIT: It is definetly objectAtIndexPath: fault. When I comment all the cell setup code (it will display empty cell) and then try to remove the cell, app crashes on line which contains objectatIndexPath:.
EDIT #2: Anybody? Please, help me... :(
I think I see the problem. In your NSArrayToDataTransformer, you have this:
- (id)reverseTransformedValue:(id)value {
NSArray *array = [NSKeyedUnarchiver unarchiveObjectWithData:value];
return [array autorelease];
}
Since unarchiveObjectWithData: does not begin with "alloc", "new", "copy", or "mutableCopy", you do not own the object and therefore may not autorelease it. You have the same problem in your NSDictionaryToDataTransformer.
Your inclusion of the value transformers into the class and the using +initialize is non-standard. Although +initialize should work, it is recommended in the Core Data docs not use any kind of initialization methods at all but to rely on awakeFromFetch for initialization.
I would check your tableview methods such as numberOfRowsInSection: to ensure you are getting the right indexes back from the tableview. If the rows in the tableview and the count of the fetchedObjects array come out of sync, you can get this kind of crash.
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?