I have 2 tables in one view controller and a search bar . The functionality of first view controller and the search bar was ok , untill i added the second table. Now when i want to search something , the research is in the table number one , and i don't want this .
Here is my code :
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
[self.searchResult removeAllObjects];
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#", searchText];
self.searchResult = [NSMutableArray arrayWithArray: [self.tableData filteredArrayUsingPredicate:resultPredicate]];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString scope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
return YES;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView.tag==1) {
if (tableView == self.searchDisplayController.searchResultsTableView)
{
return [self.searchResult count];
}
else
{return [self.tableData count];}
}
else return historique.count;
}
- (NSString *)tableView:(UITableView *)aTableView titleForHeaderInSection:(NSInteger)section {
return [[content objectAtIndex:section] objectForKey:#"headerTitle"];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return [content valueForKey:#"headerTitle"];
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
return [indices indexOfObject:title];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (tableView.tag==1) {
return [content count];
}else
return 1;
}
UITableViewCell *cell ;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
if (tableView.tag==0) {
cell = [tableView dequeueReusableCellWithIdentifier:#"cell2"];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (tableView == self.searchDisplayController.searchResultsTableView)
{
cell.textLabel.text = [self.searchResult objectAtIndex:indexPath.row];
}
else
cell.textLabel.text = [historique objectAtIndex:indexPath.row];
}
if (tableView.tag==1) {
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (tableView == self.searchDisplayController.searchResultsTableView)
{
cell.textLabel.text = [self.searchResult objectAtIndex:indexPath.row];
}
else
{
cell.textLabel.text = self.tableData[indexPath.row];
}}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
DefinitionViewController *secondViewController = [[UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]]instantiateViewControllerWithIdentifier:#"definition"];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *str = cell.textLabel.text;
NSString *uu;
if ([[transaction valueForKey:str] isKindOfClass:[NSArray class]]) {
NSLog(#"yes");
NSArray *jsonArray = (NSArray *)[transaction valueForKey:str];
uu = [jsonArray componentsJoinedByString:#"\n"];
secondViewController.definitionsArray=jsonArray;
}
else{
uu=[transaction valueForKey:str];
}
NSMutableArray *values = [[NSMutableArray alloc] initWithArray:[[NSUserDefaults standardUserDefaults] arrayForKey:#"histroriqueValues"]];
[values addObject:uu];
[[NSUserDefaults standardUserDefaults] setObject:values forKey:#"histroriqueValues"];
historiqueValue = [[[NSUserDefaults standardUserDefaults] arrayForKey:#"histroriqueValues"]mutableCopy];
[[NSUserDefaults standardUserDefaults] synchronize];
}
tableView.tag=0 is the table where i want to make the search. I put breakpoints , and when i click on search bar the table where the search is making is tableView.tag=1.
I have made a small example projects with a UITableViewController. If you need, i can push it to a github repo so you can grab it and build on it.
//
// ViewController.m
// filterExample
//
// Created by François Chabbey on 16.04.15.
// Copyright (c) 2015 François Chabbey. All rights reserved.
//
#import "ViewController.h"
#interface ViewController ()
{
NSArray *content;
NSArray *filteredContent;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
content = #[#"CECI",#"CELA",#"CELUI-CI",#"ET CA",#"ETC"];
self.tableView.dataSource = self;
self.searchDisplayController.delegate = self;
self.searchDisplayController.searchResultsDataSource = self;
self.searchDisplayController.searchResultsDelegate = self;
self.searchDisplayController.searchBar.delegate = self;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView {
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#", searchString];
filteredContent = [NSArray arrayWithArray:[content filteredArrayUsingPredicate:predicate]];
return YES;
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
return YES;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == self.tableView) {
return content.count;
} else {
return filteredContent.count;
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"test"];
if (tableView == self.tableView) {
cell.textLabel.text = content[indexPath.row];
} else {
cell.textLabel.text = filteredContent[indexPath.row];
}
return cell;
}
#end
Related
I am creating a today extension for my app, but there are some errors that I can't quite understand:
First:
Everything is Ok on the storyboard, but the button doesn't appear on the widget.
Second: When the tableview has more than one cell, the last cell gets cut.
Third: CellForRow is called, but don't change anything on the cell (Label is still "Label").
http://i.stack.imgur.com/Jp31V.png
Here's my Widget code:
#implementation TodayViewController{
NSMutableArray *listaFavoritos;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.widgetTableView.delegate = self;
self.widgetTableView.dataSource = self;
[self updateTableView];
self.preferredContentSize = self.widgetTableView.frame.size;
}
- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler {
// Perform any setup necessary in order to update the view.
// If an error is encountered, use NCUpdateResultFailed
// If there's no update required, use NCUpdateResultNoData
// If there's an update, use NCUpdateResultNewData
completionHandler(NCUpdateResultNewData);
}
- (id)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(userDefaultsDidChange:)
name:NSUserDefaultsDidChangeNotification
object:nil];
}
return self;
}
- (void)userDefaultsDidChange:(NSNotification *)notification {
[self updateTableView];
}
- (void)updateTableView {
listaFavoritos = [[NSMutableArray alloc] init];
//listaFavoritos = [[self readArrayWithCustomObjFromUserDefaults:#"listaFavs"] mutableCopy];
[listaFavoritos addObject:#"test1"];
[listaFavoritos addObject:#"test2"];
NSLog(#"%#", listaFavoritos);
}
-(NSArray *)readArrayWithCustomObjFromUserDefaults:(NSString*)keyName
{
NSUserDefaults *sharedDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.com.kazoowa.timers"];
NSData *data = [sharedDefaults objectForKey:keyName];
NSArray *myArray = [NSKeyedUnarchiver unarchiveObjectWithData:data];
[sharedDefaults synchronize];
return myArray;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [listaFavoritos count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
WidgetTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"WidgetCell" forIndexPath:indexPath];
if (cell == nil)
{
cell.nomeTimer.text = [listaFavoritos objectAtIndex:indexPath.row];
}
NSLog(#"CellForRow");
return cell;
}
1)For your second problem, your cellIdentifier in tableView:cellForRowAtIndexPath will be "static" like this :
static NSString *cellName = #"WidgetCell";
WidgetTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellName forIndexPath:indexPath];
2)this condition will be never execute because it's never nil :
if (cell == nil)
{
cell.nomeTimer.text = [listaFavoritos objectAtIndex:indexPath.row];
}
replace it by this :
if (cell != nil)
{
cell.nomeTimer.text = [listaFavoritos objectAtIndex:indexPath.row];
}
3)Please use Pragma Mark for separate properly your code like below:
#pragma mark-UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [listaFavoritos count];
}
#pragma mark-UITableViewDelegate
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
WidgetTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"WidgetCell" forIndexPath:indexPath];
if (cell == nil)
{
cell.nomeTimer.text = [listaFavoritos objectAtIndex:indexPath.row];
}
NSLog(#"CellForRow");
return cell;
}
Hope it helps :)
Try it :
- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellName = #"WidgetCell";
WidgetTableViewCell *cell = (WidgetTableViewCell *)[theTableView dequeueReusableCellWithIdentifier:cellName];
if (cell == nil) {
cell = [[WidgetTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellName];
}
cell.textLabel.text = [listaFavoritos objectAtIndex:indexPath.row];;
return cell;
}
I am new to iOS development and trying to get help with search result. Everything is working fine but when I search a word, it doesn't show the result so I will be over thanks for your help.. Here is the code..
- (void)viewDidLoad
{
[super viewDidLoad];
mytableview.delegate = self;
mytableview.dataSource = self;
SearchBar.delegate = self;
titleArray = [[NSMutableArray alloc] initWithObjects:#"Arora town",#"Domino pizza ",#"thai hunt",nil];
subtitleArray = [[NSMutableArray alloc] initWithObjects:#"wX<w (rHR< cg)",#"o;vDRuwkR(vXw>csK;cHed;o;wkRtd.tCd)<*kRuhRto; (vXw>urXur.tylR)<o;vDRxl.",nil];
}
here is cellForRowAtIndexPath
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *cellidentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellidentifier forIndexPath:indexPath];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellidentifier];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [self.searchResults objectAtIndex:indexPath.row];
}
else
{
cell.textLabel.text = [titleArray objectAtIndex:indexPath.row];
}
return cell;
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF beginswith[c] %#", searchText];
self.searchResults = [self.array filteredArrayUsingPredicate:predicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
Try This i Have tested.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(tableView==self.searchDisplayController.searchResultsTableView)
return _results.count;
else
return _countryNames.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier=#"Cell";
UITableViewCell *cell;
cell=[tableView dequeueReusableCellWithIdentifier:identifier];
if(cell==nil)
{
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [_results objectAtIndex:indexPath.row];
} else {
cell.textLabel.text = [_countryNames objectAtIndex:indexPath.row];
}
return cell;
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"SELF contains[cd] %#",
searchText];
NSLog(#"%#",scope);
_results = (NSMutableArray *)[_countryNames filteredArrayUsingPredicate:resultPredicate];
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
in viewDidLoad
initialize
_results=[[NSMutableArray alloc]init];
_countryNames=[[NSMutableArray alloc] initWithObjects:#"India",#"Pakistan",#"West Indies",#"Zimbabwe", nil];
connect search bar delegate from storyboard.
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)