I am new to iOS and I do not understand why when I click on my item in the cell it goes nowhere. No errors, no nothing. My segue ID is Cell. I Have a Button that works fine to add data, but I am trying to get to update the data if selected from the table.
Here is my .h and .m
DerbyProTableViewController.h:
#import <UIKit/UIKit.h>
#interface DerbyProTableViewController : UITableViewController
#property (strong) NSMutableArray *racerarray;
#end
DerbyProTableViewController.m:
#import "DerbyProTableViewController.h"
#import "DerbyProDetailViewController.h"
#interface DerbyProTableViewController ()
#end
#implementation DerbyProTableViewController
- (NSManagedObjectContext *)managedObjectContext
{
NSManagedObjectContext *context = nil;
id delegate = [[UIApplication sharedApplication] delegate];
if ([delegate performSelector:#selector(managedObjectContext)]) {
context = [delegate managedObjectContext];
}
return context;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"Cell"];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// Fetch the devices from persistent data store
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Racer"];
self.racerarray = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
[self.tableView reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (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 self.racerarray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
NSManagedObject *device = [self.racerarray objectAtIndex:indexPath.row];
[cell.textLabel setText:[NSString stringWithFormat:#"%# %#", [device valueForKey:#"lastname"], [device valueForKey:#"firstname"]]];
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;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSManagedObjectContext *context = [self managedObjectContext];
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete object from database
[context deleteObject:[self.racerarray objectAtIndex:indexPath.row]];
NSError *error = nil;
if (![context save:&error]) {
NSLog(#"Can't Delete! %# %#", error, [error localizedDescription]);
return;
}
// Remove device from table view
[self.racerarray removeObjectAtIndex:indexPath.row];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"updateracer"]){
NSManagedObject *selectedDevice = [self.racerarray objectAtIndex:[[self.tableView indexPathForSelectedRow] row]];
DerbyProDetailViewController *destinationViewController = segue.destinationViewController;
destinationViewController.derbyprodb = selectedDevice;
}
}
I'm going on just what I see in the code you pasted. I don't know what might have been setup in the storyboard but...
There's no delegate or datasource specified for the UITableView object. The UITableViewDelegate handles cell selection.
Once you've set up the delegate like this:
[self.tableview setDelegate:self];
You then need to implement:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
Like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:#"whateveryoursegueiscalled" sender:thecellyoutapped];
}
Have a read of Apple's tableview programming guide.
Chances are that you didn't add your class in the Identity inspector in your storyboard.
Select your view in the storyboard and click on identity ispector. Ensure that Class field is not empty
Related
I use Core Data to keep track of entries in a simple to do list. I use a simple UIAlertView with UITextField for the user to add new entries. The entries are saved using NSManagedObject, but the latest entry isn't added to the tableview, even after I run [self.tableView reloadData];
This GIF show how it works now:
Header file:
#import <UIKit/UIKit.h>
#interface PakkelisteViewController : UITableViewController <UIAlertViewDelegate>
#end
Implementation file:
#import "PakkelisteViewController.h"
#import "AUFToDoItem.h"
#interface PakkelisteViewController ()
#property NSMutableArray *toDoItems;
-(IBAction)addNewToDoItem;
#end
#implementation PakkelisteViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// defaultTodos = [[NSMutableArray alloc] initWithObjects:#"Badetøy", #"Skrivesaker", #"Lommepenger", #"Godt humør", nil];
self.toDoItems = [[NSMutableArray alloc] init];
[self loadInitialData];
// 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;
}
-(void)viewWillAppear:(BOOL)animated
{
// Fetch the devices from persistent data store
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"AUFToDoItem"];
self.toDoItems = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
[self.tableView reloadData];
}
-(void)loadInitialData
{
}
-(IBAction)addNewToDoItem
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Legg til ny" message:nil delegate:self cancelButtonTitle:#"Avbryt" otherButtonTitles:#"Legg til", nil];
[alertView setAlertViewStyle:UIAlertViewStylePlainTextInput];
[[alertView textFieldAtIndex:0] setPlaceholder:#"Rent undertøy"];
[[alertView textFieldAtIndex:0] setAutocapitalizationType:UITextAutocapitalizationTypeSentences];
[alertView show];
}
-(BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView
{
NSString *inputText = [[alertView textFieldAtIndex:0] text];
if ([inputText length] > 0)
{
return YES;
}
else
{
return NO;
}
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1)
{
NSManagedObjectContext *context = [self managedObjectContext];
// Create a new managed object
NSManagedObject *toDoItem = [NSEntityDescription insertNewObjectForEntityForName:#"AUFToDoItem" inManagedObjectContext:context];
[toDoItem setValue:[alertView textFieldAtIndex:0].text forKey:#"itemName"];
[toDoItem setValue:[NSDate date] forKey:#"creationDate"];
[toDoItem setValue:NO forKey:#"completed"];
NSError *error = nil;
// Save the object to persistent store
if (![context save:&error]) {
NSLog(#"Can't Save! %# %#", error, [error localizedDescription]);
}
[self dismissViewControllerAnimated:YES completion:nil];
[self.tableView reloadRowsAtIndexPaths:[self.tableView indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationFade];
// [self.tableView reloadData];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (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 self.toDoItems.count;
}
- (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];
}
NSManagedObject *toDoItem = [self.toDoItems objectAtIndex:indexPath.row];
cell.textLabel.text = [toDoItem valueForKey:#"itemName"];
if ((BOOL)[toDoItem valueForKey:#"completed"] == YES)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
/*
[tableView deselectRowAtIndexPath:indexPath animated:NO];
AUFToDoItem *tappedItem = [self.toDoItems objectAtIndex:indexPath.row];
tappedItem.completed = !tappedItem.completed;
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
*/
}
-(NSManagedObjectContext *)managedObjectContext {
NSManagedObjectContext *context = nil;
id delegate = [[UIApplication sharedApplication] delegate];
if ([delegate performSelector:#selector(managedObjectContext)]) {
context = [delegate managedObjectContext];
}
return context;
}
// 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;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSManagedObjectContext *context = [self managedObjectContext];
if (editingStyle == UITableViewCellEditingStyleDelete) {
[context deleteObject:[self.toDoItems objectAtIndex:indexPath.row]];
NSError *error = nil;
if (![context save:&error])
{
NSLog(#"Can't delete! %# %#", error, [error localizedDescription]);
return;
}
[self.toDoItems removeObjectAtIndex:indexPath.row];
[self.tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
You need to add the new toDoItem to your array as well. Try this :
// Create a new managed object
NSManagedObject *toDoItem = [NSEntityDescription insertNewObjectForEntityForName:#"AUFToDoItem" inManagedObjectContext:context];
[toDoItem setValue:[alertView textFieldAtIndex:0].text forKey:#"itemName"];
[toDoItem setValue:[NSDate date] forKey:#"creationDate"];
[toDoItem setValue:NO forKey:#"completed"];
[self.toDoItems addObject:toDoItem];
[self.tableView reloadData];
You should update your dataSource self.toDoItems as it still stays the same as off in viewDidLoad method. You're only saving it in CoreData, but not refreshing your dataSourse and [tableView reloadData] wont do anything
The problem lies on my didSelectRowAtIndexPath , once I click the cell the this appears on my Debug Area, I don't understand it, I'm sorry people because i'm only a beginner for now.
2014-05-08 12:59:41.118 MyWishlistV2[1334:60b] -[NSManagedObject wishlistItem]: unrecognized selector sent to instance 0x8e69c80
2014-05-08 12:59:41.121 MyWishlistV2[1334:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSManagedObject wishlistItem]: unrecognized selector sent to instance 0x8e69c80'
What I am trying to accomplish is that when I click the cell, it will go to the other ViewController(DetailViewController) but I don't know why this ain't working. Can someone check what I am doing wrong here? Here is my code.
#import "WishTableViewController.h"
#import "WishlistItem.h"
#import "DetailViewController.h"
#interface WishTableViewController ()
#property (strong) NSMutableArray *wishes;
#end
#implementation WishTableViewController
- (NSManagedObjectContext *)managedObjectContext
{
NSManagedObjectContext *context = nil;
id delegate = [[UIApplication sharedApplication] delegate];
if ([delegate performSelector:#selector(managedObjectContext)]) {
context = [delegate managedObjectContext];
}
return context;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// Fetch the wishes from persistent data store
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Wish"];
self.wishes = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
[self.tableView reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
//#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//#warning Incomplete method implementation.
// Return the number of rows in the section.
return self.wishes.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
NSManagedObject *wish = [self.wishes objectAtIndex:indexPath.row];
//Set Wish
NSString *myWish = [wish valueForKey:#"wishItem"];
NSString *myTargetDate = [wish valueForKey:#"wishTargetDate"];
cell.textLabel.text = myWish;
cell.detailTextLabel.text = myTargetDate;
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;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSManagedObjectContext *context = [self managedObjectContext];
if (editingStyle == UITableViewCellEditingStyleDelete) {
[context deleteObject:[self.wishes objectAtIndex:indexPath.row]];
NSError *error = nil;
if (![context save:&error]) {
NSLog(#"Can't Delete! %# %#", error, [error localizedDescription]);
return;
}
}
// Remove wish from table view
[self.wishes removeObjectAtIndex:indexPath.row];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
WishlistItem *wish = [self.wishes objectAtIndex:indexPath.row];
DetailViewController *dvc = [self.storyboard instantiateViewControllerWithIdentifier:#"dvcID"];
dvc.wishItemStr = wish.wishlistItem;
dvc.dateItemStr = wish.targetDate;
dvc.descItemStr = wish.descWishItem;
[self.navigationController pushViewController:dvc animated:YES];
}
#end
Its important to setup and use NSFetchedResultsController for example
MyObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
I am fairly new to Xcode so I have been using a tutorial on how to implement a SearchBar in my notes app. The SearchBar retrieves the data from the table view but when I click on it it doesn't take me to the page. How would I fix this problem in UIStoryboardSegue keeping in mind I'm new to all this stuff! Thanks in advance:3
#import "DeviceViewController.h"
#import "DeviceDetailViewController.h"
#interface DeviceViewController ()
#property (strong) NSMutableArray *devices;
#end
#implementation DeviceViewController
{
NSArray *searchResults;
}
- (NSManagedObjectContext *)managedObjectContext {
NSManagedObjectContext *context = nil;
id delegate = [[UIApplication sharedApplication] delegate];
if ([delegate performSelector:#selector(managedObjectContext)]) {
context = [delegate managedObjectContext];
}
return context;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
//label.backgroundColor = [UIColor clearColor];
label.font = [UIFont fontWithName:#"HelveticaNeue-thin" size:28];
//label.shadowColor = [UIColor colorWithWhite:0.0 alpha:0.5];
label.textColor = [UIColor blackColor];
self.navigationItem.titleView = label;
label.text = #"TapNotes";
[label sizeToFit];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// Fetch the devices from persistent data store
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Device"];
self.devices = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
[self.tableView reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [searchResults count];
} else {
return self.devices.count;
}
//return self.devices.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell==nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]; }
NSManagedObject *device = [self.devices objectAtIndex:indexPath.row];
[cell.textLabel setText:[NSString stringWithFormat:#"%#", [device valueForKey:#"name"]]];
[cell.detailTextLabel setText:[NSString stringWithFormat:#"%#",[device valueForKey:#"version"]]];
if (tableView == self.searchDisplayController.searchResultsTableView) {
device = [searchResults objectAtIndex:indexPath.row];
} else {
[self.devices objectAtIndex:indexPath.row];
}
// cell.thumbnailImageView.image = [UIImage imageNamed:recipe.image];
return cell;
}
- (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
{
NSManagedObjectContext *context = [self managedObjectContext];
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete object from database
[context deleteObject:[self.devices objectAtIndex:indexPath.row]];
NSError *error = nil;
if (![context save:&error]) {
NSLog(#"Can't Delete! %# %#", error, [error localizedDescription]);
return;
}
// Remove device from table view
[self.devices removeObjectAtIndex:indexPath.row];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"UpdateDevice"]) {
NSManagedObject *selectedDevice = [self.devices objectAtIndex:[[self.tableView indexPathForSelectedRow] row]];
NSIndexPath *indexPath = nil;
//Device *device = nil;
if (self.searchDisplayController.active) {
indexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow];
_devices = [searchResults objectAtIndex:indexPath.row];
} else {
indexPath = [self.tableView indexPathForSelectedRow];
_devices = [_devices objectAtIndex:indexPath.row];
}
DeviceDetailViewController *destViewController = segue.destinationViewController;
destViewController.device = selectedDevice;
}
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"name contains[c] %#", searchText];
searchResults = [_devices filteredArrayUsingPredicate:resultPredicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
#end
A UIStoryboardSegue can only be connected via a storyboard. Since you are presenting your search data through the UISearchDisplayController, you need to implement tableView:didSelectRowAtIndexPath:. In this method you need to make sure you are only performing a push to a new view controller when you are receiving events from the tableview connected to UISearchDisplayController In this method I would recommend you to use performSegueWithIdentifier: and manually connect a segue in you storyboard. See this answer for more details on how to create a manual segue: https://stackoverflow.com/a/17012857/1049509
I'm fairly new to Xcode and am having trouble getting my head around why the table view data isn't displaying in the searchbar. Basically trying to return fetched results to a searchbar. Thanks in advance!
#import "DeviceViewController.h"
#import "DeviceDetailViewController.h"
#interface DeviceViewController ()
#property (strong) NSMutableArray *devices;
#end
#implementation DeviceViewController
{
NSArray *recipes;
NSArray *searchResults;
}
#synthesize recipe;
- (NSManagedObjectContext *)managedObjectContext {
NSManagedObjectContext *context = nil;
id delegate = [[UIApplication sharedApplication] delegate];
if ([delegate performSelector:#selector(managedObjectContext)]) {
context = [delegate managedObjectContext];
}
return context;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
//label.backgroundColor = [UIColor clearColor];
label.font = [UIFont fontWithName:#"HelveticaNeue-thin" size:28];
//label.shadowColor = [UIColor colorWithWhite:0.0 alpha:0.5];
label.textColor = [UIColor blackColor];
self.navigationItem.titleView = label;
label.text = #"TapNotes";
[label sizeToFit];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// Fetch the devices from persistent data store
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Device"];
self.devices = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
[self.tableView reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [searchResults count];
} else {
return self.devices.count;
}
//return self.devices.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell==nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]; }
NSManagedObject *device = [self.devices objectAtIndex:indexPath.row];
[cell.textLabel setText:[NSString stringWithFormat:#"%#", [device valueForKey:#"name"]]];
[cell.detailTextLabel setText:[NSString stringWithFormat:#"%#",[device valueForKey:#"version"]]];
if (tableView == self.searchDisplayController.searchResultsTableView) {
recipe = [searchResults objectAtIndex:indexPath.row];
} else {
[self.devices objectAtIndex:indexPath.row];
}
// cell.thumbnailImageView.image = [UIImage imageNamed:recipe.image];
return cell;
}
- (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
{
NSManagedObjectContext *context = [self managedObjectContext];
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete object from database
[context deleteObject:[self.devices objectAtIndex:indexPath.row]];
NSError *error = nil;
if (![context save:&error]) {
NSLog(#"Can't Delete! %# %#", error, [error localizedDescription]);
return;
}
// Remove device from table view
[self.devices removeObjectAtIndex:indexPath.row];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"UpdateDevice"]) {
NSManagedObject *selectedDevice = [self.devices objectAtIndex:[[self.tableView indexPathForSelectedRow] row]];
DeviceDetailViewController *destViewController = segue.destinationViewController;
destViewController.device = selectedDevice;
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 55;
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"name contains[c] %#", searchText];
searchResults = [recipes filteredArrayUsingPredicate:resultPredicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
#end
Things don't look right here.
Why are you not using a NSFetchedResultsConteroller?
What is the connection between recipes and devices arrays
You are not setting the recipes array (you filter it on filterContentForSearchText:)
Your cellForRowAtIndexPath: always set data for cell by the devices array
You have a lot of "dead" code
It looks like you took this code from an example and modified it, but only half way.
Whenever I attempt to enter a second character into the SearchBar the app crashes with a "terminating with uncaught exception" error. The SearchBar is referencing the Table Cell data if that helps at all. How do I fix this?
#interface DeviceViewController ()
#property (strong) NSMutableArray *devices;
#end
#implementation DeviceViewController
{
NSArray *searchResults;
}
- (NSManagedObjectContext *)managedObjectContext {
NSManagedObjectContext *context = nil;
id delegate = [[UIApplication sharedApplication] delegate];
if ([delegate performSelector:#selector(managedObjectContext)]) {
context = [delegate managedObjectContext];
}
return context;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
//label.backgroundColor = [UIColor clearColor];
label.font = [UIFont fontWithName:#"HelveticaNeue-thin" size:28];
//label.shadowColor = [UIColor colorWithWhite:0.0 alpha:0.5];
label.textColor = [UIColor blackColor];
self.navigationItem.titleView = label;
label.text = #"TapNotes";
[label sizeToFit];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// Fetch the devices from persistent data store
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Device"];
self.devices = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
[self.tableView reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [searchResults count];
} else {
return self.devices.count;
}
//return self.devices.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell==nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]; }
NSManagedObject *device = [self.devices objectAtIndex:indexPath.row];
[cell.textLabel setText:[NSString stringWithFormat:#"%#", [device valueForKey:#"name"]]];
[cell.detailTextLabel setText:[NSString stringWithFormat:#"%#",[device valueForKey:#"version"]]];
if (tableView == self.searchDisplayController.searchResultsTableView) {
device = [searchResults objectAtIndex:indexPath.row];
} else {
[self.devices objectAtIndex:indexPath.row];
}
// cell.thumbnailImageView.image = [UIImage imageNamed:recipe.image];
return cell;
}
- (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
{
NSManagedObjectContext *context = [self managedObjectContext];
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete object from database
[context deleteObject:[self.devices objectAtIndex:indexPath.row]];
NSError *error = nil;
if (![context save:&error]) {
NSLog(#"Can't Delete! %# %#", error, [error localizedDescription]);
return;
}
// Remove device from table view
[self.devices removeObjectAtIndex:indexPath.row];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"UpdateDevice"]) {
NSManagedObject *selectedDevice = [self.devices objectAtIndex:[[self.tableView indexPathForSelectedRow] row]];
NSIndexPath *indexPath = nil;
if (self.searchDisplayController.active) {
indexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow];
_devices = [searchResults objectAtIndex:indexPath.row];
} else {
indexPath = [self.tableView indexPathForSelectedRow];
_devices = [_devices objectAtIndex:indexPath.row];
}
DeviceDetailViewController *destViewController = segue.destinationViewController;
destViewController.device = selectedDevice;
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 55;
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"name contains[c] %#", searchText];
searchResults = [_devices filteredArrayUsingPredicate:resultPredicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
#end
You have many table view managing issues.
As I mentioned HERE, Use a NSFetchedResultsController (or open an empty project that include CoreData and see how easy table management will be when you have one).
You can't filter your search array without notifying the table that it needs to be reloaded.
The table view must know the count of the datasource as it will expect this data to exist when it asks for it in cellForRow...
Also, you treat your _device variable once as an NSArray and one as a managed object (in cellForRow...).
in cellForRow... change _device to device ...
and then you will have a new problem ...
(look at the advices I gave you in your previous question)