I am not sure how I could approach this, I am just learning about tables. I have the code below that filters an array as you type. The search bar moves up and the controller goes dark below the search, however when I type the first letter, the results don't generate underneath.
This is a modification of the sample project from Apple. Tablesearch
What am I missing?
Also the keyboard seems to drag behind when the new VC loads
Thank you in advance
// itemsSearchViewController.m
#import "itemsSearchViewController.h"
#import "SearchRecipeViewController.h"
#import "firstAppDelegate.h"
#interface itemsSearchViewController ()
#end
#implementation itemsSearchViewController
#synthesize listContent, filteredListContent, savedSearchTerm, savedScopeButtonIndex, searchWasActive;
#synthesize delegate;
#synthesize itemsToPass;
/*
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
#pragma mark -
#pragma mark Lifecycle methods
*/
- (void)viewDidLoad
{
//[super viewDidLoad];
self.title = #"items Search";
//write names of itemss to array
NSString *path =[[NSBundle mainBundle] pathForResource:#"possibleitemss" ofType:#"plist"];
NSArray *content = [NSArray arrayWithContentsOfFile:path];
self.listContent =[NSArray arrayWithArray:content];
if([content count] == 0)
{
NSLog(#"nsma is empty");
}
NSLog(#"list contents%#", listContent);
// NSLog(#"list content = %#", listContent);
// create a filtered list that will contain products for the search results table.
self.filteredListContent = [NSMutableArray arrayWithCapacity:[self.listContent count]];
// restore search settings if they were saved in didReceiveMemoryWarning.
if (self.savedSearchTerm)
{
[self.searchDisplayController setActive:self.searchWasActive];
[self.searchDisplayController.searchBar setSelectedScopeButtonIndex:self.savedScopeButtonIndex];
[self.searchDisplayController.searchBar setText:savedSearchTerm];
self.savedSearchTerm = nil;
}
[self.tableView reloadData];
self.tableView.scrollEnabled = YES;
}
- (void)viewDidUnload
{
//self.filteredListContent = nil;
}
- (void)viewDidDisappear:(BOOL)animated
{
// save the state of the search UI so that it can be restored if the view is re-created
self.searchWasActive = [self.searchDisplayController isActive];
self.savedSearchTerm = [self.searchDisplayController.searchBar text];
self.savedScopeButtonIndex = [self.searchDisplayController.searchBar selectedScopeButtonIndex];
}
- (void)dealloc
{
[listContent release];
[filteredListContent release];
[super dealloc];
}
#pragma mark -
#pragma mark UITableView data source and delegate methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
/*
If the requesting table view is the search display controller's table view, return the count of
the filtered list, otherwise return the count of the main list.
*/
if (tableView == self.searchDisplayController.searchResultsTableView)
{
return [self.filteredListContent count];
}
else
{
return [self.listContent count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *kCellID = #"cellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellID];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellID] autorelease];
}
/*
If the requesting table view is the search display controller's table view, configure the cell using the filtered content, otherwise use the main list.
*/
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
/*
If the requesting table view is the search display controller's table view, configure the next view controller using the filtered content, otherwise use the main list.
*/
}
#pragma mark -
#pragma mark Content Filtering
//as user types this is happening
-(void) filterResults:(NSString *)searchText{
NSMutableArray *test = [NSMutableArray arrayWithArray:self.listContent];
[self.filteredListContent removeAllObjects]; // First clear the filtered array.
for (int i=0; i<[test count]; i++) {
NSString *stringResult = [test objectAtIndex:i];
NSComparisonResult result = [stringResult compare:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [searchText length])];
if (result == NSOrderedSame){
[self.filteredListContent addObject:stringResult];
}
}
[self.filteredListContent sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];//sort alphabetically
NSLog(#"filtered results = %#",self.filteredListContent);
}
#pragma mark -
#pragma mark UISearchDisplayController Delegate Methods
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{items
[self filterResults:searchString];
//[self filterContentForSearchText:searchString scope:
// [[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
// Return YES to cause the search result table view to be reloaded.
return YES;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
[self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope:
[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];
// Return YES to cause the search result table view to be reloaded.
return YES;
}
- (IBAction)itemsSelected: (id)sender{
if ( self.delegate != nil && [self.delegate respondsToSelector:#selector(showSearchRecipeView)] ) {
[self.delegate showSearchRecipeView];
}
}
#end
My guess is that one the below is out:
The resource path is possibleitemss -- is that a typo?
Have you verified that the arrays have been populated?
Is your searchDisplayController:shouldReloadTableForSearchScope: actually returning yes?
In other words, I'd step into each of these functions and watch the that the flow is behaving how you expected, and that your arrays are in fact populated.
Let me know if that helps.
Related
I followed this tutorial from AppCoda and I noticed that when I create another calendar, choose it (indicated by the checkmark beside it), then hit the Back button, the events in the main UIViewController view are not refreshed. I already added this code in my ViewController.m but nothing new happened:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (self.tblEvents == nil) {
NSLog(#"Your TableView becomes nil");
return;
}
[self.tblEvents reloadData];
}
Any ideas? Let me know if you need more information.
Edit:
.m
#import "MainViewController.h"
#import "AppDelegate.h"
#interface MainViewController ()
#property (nonatomic, strong) AppDelegate *appDelegate;
#property (nonatomic, strong) NSArray *arrEvents;
- (void)requestAccessToEvents;
- (void)loadEvents;
#end
#implementation MainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
self.tblEvents.delegate = self;
self.tblEvents.dataSource = self;
[self performSelector:#selector(requestAccessToEvents) withObject:nil afterDelay:0.4];
[self performSelector:#selector(loadEvents) withObject:nil afterDelay:0.5];
[self.tblEvents reloadData];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.tblEvents reloadData];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"idSegueEvent"]) {
EventViewController *eventViewController = [segue destinationViewController];
eventViewController.delegate = self;
}
}
#pragma mark - UITableView Delegate and Datasource method implementation
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"%lu", (unsigned long)self.arrEvents.count);
return self.arrEvents.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"idCellEvent"];
// Get each single event.
EKEvent *event = [self.arrEvents objectAtIndex:indexPath.row];
// Set its title to the cell's text label.
cell.textLabel.text = event.title;
// Get the event start date as a string value.
NSString *startDateString = [self.appDelegate.eventManager getStringFromDate:event.startDate];
// Get the event end date as a string value.
NSString *endDateString = [self.appDelegate.eventManager getStringFromDate:event.endDate];
// Add the start and end date strings to the detail text label.
cell.detailTextLabel.text = [NSString stringWithFormat:#"%# - %#", startDateString, endDateString];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 60.0;
}
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
// Keep the identifier of the event that's about to be edited.
self.appDelegate.eventManager.selectedEventIdentifier = [[self.arrEvents objectAtIndex:indexPath.row] eventIdentifier];
// Perform the segue.
[self performSegueWithIdentifier:#"idSegueEvent" sender:self];
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the selected event.
[self.appDelegate.eventManager deleteEventWithIdentifier:[[self.arrEvents objectAtIndex:indexPath.row] eventIdentifier]];
// Reload all events and the table view.
[self loadEvents];
}
}
#pragma mark - EEventViewControllerDelegate method implementation
- (void)eventWasSuccessfullySaved
{
// Reload all events.
[self loadEvents];
}
#pragma mark - IBAction method implementation
- (IBAction)showCalendars:(id)sender
{
if (self.appDelegate.eventManager.eventsAccessGranted) {
[self performSegueWithIdentifier:#"idSegueCalendars" sender:self];
}
}
- (IBAction)createEvent:(id)sender
{
if (self.appDelegate.eventManager.eventsAccessGranted) {
[self performSegueWithIdentifier:#"idSegueEvent" sender:self];
}
}
#pragma mark - Private method implementation
- (void)requestAccessToEvents
{
[self.appDelegate.eventManager.eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
if (error == nil) {
// Store the returned granted value.
self.appDelegate.eventManager.eventsAccessGranted = granted;
} else {
// In case of error, just log its description to the debugger.
NSLog(#"%#", [error localizedDescription]);
}
}];
}
- (void)loadEvents
{
if (self.appDelegate.eventManager.eventsAccessGranted) {
self.arrEvents = [self.appDelegate.eventManager getEventsOfSelectedCalendar];
[self.tblEvents reloadData];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
To make UITableView work you need to set the delegate and datasource object like this..
in you ViewController.m file try to add Delegate and DataSource like this.
#interface ViewController ()<UITableViewDelegate, UITableViewDataSource>
#end
now add these two lines in your view did load.
self.tblEvents.delegate = self;
self.tblEvents.dataSource = self;
And check the implimentation of you Data Source methods like this
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//This method should return the number of rows you want to create in your tableView
return yourArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"yourCellIdentifier"];
//Now show what you want to show in your each cell? For Example you just want to show a simple text which is stored in you array.
cell.textLabel.text = [yourArray objectAtIndex:indexPath.row];
//indexPath.row is the numeric index number of each cell. This method will automatically execute exact the same number of time you return in above method.
return cell;
}
Now When your class/View Controller is open you might have zero data in your array and after some manipulation you got some data in your array Either by Call Web-Services/Loading from local Database/ by Passing Reference of array to next ViewController and on coming back to screen you want to refresh your TableView so now calling [tblEvents reloadData] will restart the process from numberOfRowsInSection method to cellForRowAtIndexPath method
I have 2 Controllers, 1 is to load data from JSON, the other is a simple UITableViewController. My problem is that the view is loaded before the data. How can I make the data load before my table? I'm new to Objective-C OOP :/
the code
#import "MasterViewController.h"
#import "DetailViewController.h"
#import "DealsDataController.h"
#import "Deals.h"
#implementation MasterViewController
- (void)awakeFromNib
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
self.clearsSelectionOnViewWillAppear = NO;
self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0);
}
[super awakeFromNib];
self.dataController = [[DealsDataController alloc] init];
NSLog(#"this is the awake from nib count %i",[self.dataController countOfList]);
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"did this count the list %i",[self.dataController countOfList]);
return [self.dataController countOfList];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"DealCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
Deals *dealAtIndex = [self.dataController objectInListAtIndex:indexPath.row];
[[cell textLabel] setText:dealAtIndex.name];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return NO;
}
/*
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
[_objects removeObjectAtIndex:indexPath.row];
[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.
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
NSDate *object = _objects[indexPath.row];
self.detailViewController.detailItem = object;
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSDate *object = _objects[indexPath.row];
[[segue destinationViewController] setDetailItem:object];
}
}
*/
#end
and the Data Controller
#import "DealsDataController.h"
#import "Deals.h"
#implementation DealsDataController
#synthesize masterDealsList = _masterDealsList;
-(id)init {
if (self = [super init]) {
[self initializeDataList];
return self;
}
return nil;
}
-(NSMutableArray *)masterDealsList {
if (!_masterDealsList) {
_masterDealsList = [[NSMutableArray alloc] init];
}
return _masterDealsList;
}
-(void)setMasterDealsList:(NSMutableArray *)newList {
if (_masterDealsList != newList) {
_masterDealsList = newList;
}
}
- (void)fetchedData:(NSData *)responseData {
//parse out the json data
NSError* error;
NSDictionary *json = [NSJSONSerialization
JSONObjectWithData:responseData //1
options:kNilOptions
error:&error];
_deals = [json objectForKey:#"deals"]; //2
NSLog(#"deals: %#", _deals);
NSArray *dealName = [_deals valueForKey:#"deal_name"];
NSLog(#"deals Name: %#", dealName);
for (int i = 1;i <= [_deals count]; i++) {
NSDictionary* dict = [_deals objectAtIndex:i-1];
Deals *deal =[[Deals alloc] initWithProdID:1 name:[dict valueForKey:#"deal_name"] description:[dict objectForKey:#"deal_description"] price:10.00 specs:#"specs" terms:#"terms"];
[self addDealWithDeal:deal];
NSLog (#"masterListCount %i ", [self countOfList]);
}
}
-(void)initializeDataList {
//NSDate *today = [NSDate date];
dispatch_async(sweetDealsQueue, ^{
NSData* data = [NSData dataWithContentsOfURL:sweetDealsURL];
[self performSelectorOnMainThread:#selector(fetchedData:)
withObject:data waitUntilDone:YES];
});
}
-(NSUInteger)countOfList {
return [self.masterDealsList count];
}
-(Deals *)objectInListAtIndex:(NSUInteger)theIndex {
return [self.masterDealsList objectAtIndex:theIndex];
}
-(void)addDealWithDeal:(Deals *)deal {
[self.masterDealsList addObject:deal];
}
#end
In MVC, you'd typically have one view controller per view. So a single view controller would be responsible for everything display on one view. Of course, you can have helper classes, or use sub view controllers (e.g. widgets), or if you're developing for iPad, you might have two view controllers (one for the side menu, one for the main view).
I'd suggest you do the following
Make your DataController a subclass of NSObject instead of UIViewController. From what I understand, it is a data access class, not responsible for UI.
In the viewDidLoad method of your MasterViewController, allocate and initialise a DataController object and trigger its data load method.
Either set a callback so when data is fetched, a method on the MasterViewController is called with the data. Or set your MasterViewController as a delegate for your DataController and when it's done, assign the data to a property of the MasterViewController.
i guess you need to perform Data loading before initialising your TableViewController and as you get response Data load the TableViewController. for that refer this post how to wait until some method complete execution, perform data loading in that method.
Its okay to display a blank tableview with an activity indicator overlay while the data is loading. When the data has finished loading, you can just reload the tableview with the data and remove the activity indicator. [tableview reloaddata] would call all of the datasource delegate methods which would then have your data in it.
I am trying to link from a dynamic table view cell (as part of a search result table) to a specific view controller
The code I have implemented so far is:
SearchViewController.h
import <UIKit/UIKit.h>
#interface SearchViewController : UITableViewController <UISearchDisplayDelegate, UISearchDisplayDelegate>
#property (strong,nonatomic) NSArray *sysTArray;
#property (strong,nonatomic) NSMutableArray *filteredsysTArry;
#property IBOutlet UISearchBar *sysTSearchBar;
#end
SearchViewController.M
#import "SearchViewController.h"
#import "sysT.h"
#interface SearchViewController ()
#end
#implementation SearchViewController
#synthesize sysTArray;
#synthesize filteredsysTArry;
#synthesize sysTSearchBar;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
sysTArray = [NSArray arrayWithObjects:
[sysT sysTOfCategory:#"p" name:#"H1"],
[sysT sysTOfCategory:#"p" name:#"W2"],
[sysT sysTOfCategory:#"p" name:#"W3"],
[sysT sysTtOfCategory:#"p" name:#"C4"],
[sysT sysTOfCategory:#"c" name:#"O5"],
[sysT sysTOfCategory:#"c" name:#"C6"],
[sysT sysTOfCategory:#"a" name:#"L7"], nil];
self.filteredSysTArry = [NSMutableArray arrayWithCapacity:[sysTArray count]];
[self.tableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [filteredsysTArry count];
}else{
return [sysTArray count];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (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];
}
SysT *sysT = nil;
if (tableView == self.searchDisplayController.searchResultsTableView) {
sysT = [filteredsysTArry objectAtIndex:indexPath.row];
}else{
sysT = [sysTArray objectAtIndex:indexPath.row];
}
cell.textLabel.text = sysT.name;
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
return cell;
}
#pragma mark Search Filtering
-(void)filterContentForSearchText:(NSString*) searchText scope:(NSString*)scope {
[self.filteredSysTArry removeAllObjects];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.name contains[c] %#", searchText];
filteredSysTArry = [NSMutableArray arrayWithArray:[sysTArray filteredArrayUsingPredicate:predicate]];
}
#pragma mark - UISearchDisplayController Delegate Methods
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self filterContentForSearchText:searchString scope:
[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex: [self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
return YES;
}
-(BOOL) searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
[self filterContentForSearchText:self.searchDisplayController.searchBar.text scope:
[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];
return YES;}
#end
How do I initiate a specific view controller depending on the data inside the dynamic cell?
To further elaborate, if a user searched H1, and then clicked on that dynamic cell, how would I display the relevant H1 view controller?
As you can probably tell from my very rough code, I'm on a steep learning curve. If you could make your answers as baby proof as possible that would be fantastic, and would really help me out. (Also, I am using storyboards).
Thanks!
You need to implement tableView:didSelectRowAtIndexPath: which is called when you select a row. You can get the data for that row by querying your data source, using the indexPath passed into that method. You can then use whatever logic you need to choose which view controller to go to next. You do that by calling performSegueWithIdentifier.
I created a subClass of UITextView with a searchBar, here is the code:
#import "SezioniTableController.h"
#interface SezioniTableController ()
#end
#implementation SezioniTableController
#synthesize searchBar,searchDisplayController;
#synthesize arraySezioni,arrayFiltrato;
#synthesize objTesto;
- (id)initWithStyle:(UITableViewStyle)style andArray:(NSMutableArray *)array{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44)];
self.searchBar.delegate = self;
self.searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
self.searchDisplayController.delegate = self;
self.searchDisplayController.searchResultsDataSource = self;
self.arraySezioni = array;
self.arrayFiltrato = array;
}
return self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void) loadView {}
#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.arrayFiltrato.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyIdentifier"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewStylePlain reuseIdentifier:#"MyIdentifier"];
}
self.objTesto = [arrayFiltrato objectAtIndex:indexPath.row];
cell.textLabel.text = self.objTesto.titoloTesto;
return cell;
}
#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];
*/
NSDictionary *dict = [NSDictionary dictionaryWithObject:[self.arrayFiltrato objectAtIndex:indexPath.row] forKey:#"Testo"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"PassaggioTesto" object:self userInfo:dict];
NSLog(#"Click");
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
return self.searchBar; //in .h, IBOutlet UISearchBar* search;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 44;
}
- (BOOL) searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString{
[self filterContentForSearchText:searchString scope: [[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
NSLog(#"aa");
//[[NSNotificationCenter defaultCenter] postNotificationName:#"ReloadTable" object:self];
// Return YES to cause the search result table view to be reloaded.
return YES;
}
- (BOOL) searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption{
[self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];
NSLog(#"ab");
//[[NSNotificationCenter defaultCenter] postNotificationName:#"ReloadTable" object:self];
// Return YES to cause the search result table view to be reloaded.
return YES;
}
- (void) filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope{
NSLog(#"a count:%d",self.arraySezioni.count);
[self.arrayFiltrato removeAllObjects]; // First clear the filtered array.
for (objTesto in self.arraySezioni){
NSComparisonResult result = [objTesto.titoloTesto compare:searchText options:NSCaseInsensitiveSearch range:NSMakeRange(0, [searchText length])];
if (result == NSOrderedSame){
NSLog(#"Titolo: %#",objTesto.titoloTesto);
[self.arrayFiltrato addObject:self.objTesto];
}else{
NSLog(#"Non trovato");
}
}
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)saearchBar {
[self.arrayFiltrato removeAllObjects];
[self.arrayFiltrato addObjectsFromArray: self.arraySezioni];
}
#end
On my uiviewcontroller I create a table using the uitableview created with this code:
self.arrayTesti = [self.dataLoad leggiArgomentiDellaSezione:tag];
self.table = [[SezioniTableController alloc] initWithStyle:UITableViewStylePlain andArray:self.arrayTesti];
self.tableArgumentView.delegate = self.table;
self.tableArgumentView.dataSource = self.table;
[self.tableArgumentView reloadData];
The viewcontroller is for an iPad application, the table works perfectly but if I try to search something it doesn't work!
Can you help me?
If you assign
self.arraySezioni = array;
self.arrayFiltrato = array;
then both self.arraySezioni and self.arrayFiltrato are pointers to the same array. Which means that if you empty one array with
[self.arrayFiltrato removeAllObjects];
then the other array self.arraySezioni (and the original array) are also empty.
So at least self.arrayFiltrato should be a copy of the original array:
self.arrayFiltrato = [array copy];
I use the following method to present a UIViewController named DictAddSubSecondCell:
// UIViewControler 1
- (IBAction)addWord:(id)sender{
dictAddSubSecondCellController = [[DictAddSubSecondCell alloc] initWithNibName:#"DictAddSubSecondCell" bundle:nil];
[self presentModalViewController:dictAddSubSecondCellController animated:YES];
[dictAddSubSecondCellController release];
}
and when I click the button in DictAddSubSecondCell:
- (IBAction)dismissAction:(id)sender{
[self dismissModalViewControllerAnimated:YES];
}
the tableView at UIViewControler 1 didn't reload it's data, but I added a method in viewWillApear method:
[self.table reloadData];
but it still not work. I have no idea about this. Is there any suggestions for me? thanks.
Here is the full source code of UIViewcontroller 1:
//
// DictAddSubSecond.m
//
// Created by Samuel Armstrong on 4/8/12.
// Copyright 2012 __MyCompanyName__. All rights reserved.
//
#import "DictAddSubSecond.h"
#import "DictionaryList.h"
#implementation DictAddSubSecond
#synthesize dictList, table, editButton;
#synthesize dictAddSubSecondCellController;
- (IBAction)addWord:(id)sender
{
dictAddSubSecondCellController = [[DictAddSubSecondCell alloc] initWithNibName:#"DictAddSubSecondCell" bundle:nil];
[self presentModalViewController:dictAddSubSecondCellController animated:YES];
[dictAddSubSecondCellController release];
}
- (IBAction)toggleEdit {
[self.table setEditing:!self.table.editing animated:YES];
if (self.table.editing) {
[editButton setTitle:#"Done"];
[editButton setStyle:UIBarButtonItemStyleDone];
}
else {
[editButton setTitle:#"Edit"];
[editButton setStyle:UIBarButtonItemStyleBordered];
}
}
- (IBAction)dismissAction:(id)sender
{
[self dismissModalViewControllerAnimated:NO];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)refreshTableData
{
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *file = [path stringByAppendingPathComponent:#"dictWithWords.tmp"];
if (dictList == nil) {
NSMutableArray *array = [[NSMutableArray alloc] initWithContentsOfFile:file];
if ([array objectAtIndex:0] != nil) {
dictList = [[NSMutableArray alloc] initWithCapacity:1];
self.dictList = array;
[array release];
}
else
{
dictList = [[NSMutableArray alloc] initWithCapacity:1];
}
}
[self.table reloadData];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self refreshTableData];
}
- (void)someMethodToReloadTable:(NSNotification *)notification
{
[table reloadData];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(someMethodToReloadTable) name:#"reloadTable" object:nil];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"reloadTable" object:nil];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark -
#pragma mark Table View Data Source Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [dictList count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MoveMeCellIdentifier = #"MoveMeCellIdentifier";
UITableViewCell *cell = [self.table dequeueReusableCellWithIdentifier:MoveMeCellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:MoveMeCellIdentifier] autorelease];
//A Boolean value that determines whether the cell shows the reordering control.
cell.showsReorderControl = YES;
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [dictList objectAtIndex:row];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
#pragma mark -
#pragma mark Table View Delegate Methods
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger row = [indexPath row];
[self.dictList removeObjectAtIndex:row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationMiddle];
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleDelete;
}
// Asks the data source whether a given row can be moved to another location in the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
//Tells the data source to move a row at a specific location in the table view to another location.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
NSUInteger fromRow = [fromIndexPath row];
NSUInteger toRow = [toIndexPath row];
id object = [[dictList objectAtIndex:fromRow] retain];
[dictList removeObjectAtIndex:fromRow];
[dictList insertObject:object atIndex:toRow];
[object release];
}
#end
Try calling it in viewDidAppear: instead of viewWillAppear:.