Set TV Menu Button To Go Back One Screen - objective-c

My Apple TV app lists a collection of PDFs, and clicking one draws it on the screen. For some reason, though, it exits the app completely when someone hits the < / Menu button on the Apple TV Remote. What is going on to cause it to do that?
Up first is the code where it pulls up the list of all the PDFs, followed by the code for displaying the PDF.
-(void)viewDidLoad {
[super viewDidLoad];
self.definesPresentationContext = YES; // know where you want UISearchController to be displayed
}
- (void)viewWillAppear:(BOOL)animated {
if (self.searchControllerWasActive) {
self.searchController.active = self.searchControllerWasActive;
_searchControllerWasActive = NO;
if (self.searchControllerSearchFieldWasFirstResponder) {
[self.searchController.searchBar becomeFirstResponder];
_searchControllerSearchFieldWasFirstResponder = NO;
}
}
NSBundle *bundle = [NSBundle mainBundle];
self.files = [bundle pathsForResourcesOfType:#"pdf" inDirectory:#"AIMPDF"];
NSString *documentsDirectoryPath = [self.files objectAtIndex:thepath.row];
self.title = #"Devo Songs";
self.filenames = [[documentsDirectoryPath lastPathComponent] stringByDeletingPathExtension];
NSLog(#"%#", filenames);
NSMutableArray *names = [NSMutableArray arrayWithCapacity:[self.files count]];
for (NSString *path in self.files) {
[names addObject:[[path lastPathComponent] stringByDeletingPathExtension]];
}
self.files = names;
self.files = [names sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
self.tableView.backgroundColor = [UIColor whiteColor];
self.parentViewController.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"iphonebackground.png"]];
[super viewDidLoad];
[super viewWillAppear:animated];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[searchBar resignFirstResponder];
}
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
// update the filtered array based on the search text
NSString *searchText = searchController.searchBar.text;
NSMutableArray *searchResults2 = [self.files mutableCopy];
// strip out all the leading and trailing spaces
NSString *strippedString = [searchText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
// break up the search terms (separated by spaces)
NSArray *searchItems = nil;
if (strippedString.length > 0) {
searchItems = [strippedString componentsSeparatedByString:#" "];
}
// build all the "AND" expressions for each value in the searchString
//
NSMutableArray *andMatchPredicates = [NSMutableArray array];
for (NSString *searchString in searchItems) {
NSPredicate *sPredicate =
[NSPredicate predicateWithFormat:#"SELF contains[c] %#", searchString];
[searchResults2 filterUsingPredicate:sPredicate];
// at this OR predicate to our master AND predicate
// NSCompoundPredicate *orMatchPredicates = [NSCompoundPredicate orPredicateWithSubpredicates:searchItemsPredicate];
//[andMatchPredicates addObject:orMatchPredicates];
}
// match up the fields of the Product object
// NSCompoundPredicate *finalCompoundPredicate =
//[NSCompoundPredicate andPredicateWithSubpredicates:andMatchPredicates];
//searchResults2 = [[searchResults filteredArrayUsingPredicate:finalCompoundPredicate] mutableCopy];
// hand over the filtered results to our search results table
APLResultsTableController *tableController = (APLResultsTableController *)self.searchController.searchResultsController;
tableController.filteredProducts = searchResults2;
[tableController.tableView reloadData];
}
- (void)handleSearchForTerm:(NSString *)searchTerm
{
[self setSavedSearchTerm:searchTerm];
if ([self searchResults] == nil)
{
NSMutableArray *array = [[NSMutableArray alloc] init];
[self setSearchResults:array];
array = nil;
}
[[self searchResults] removeAllObjects];
if ([[self savedSearchTerm] length] != 0)
{
for (NSString *currentString in [self files])
{
if ([currentString rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location != NSNotFound)
{
[[self searchResults] addObject:currentString];
}
}
}
}- (void)viewDidUnload
{
[super viewDidUnload];
// Save the state of the search UI so that it can be restored if the view is re-created.
[self setSavedSearchTerm:[[[self searchDisplayController] searchBar] text]];
[self setSearchResults:nil];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200
if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad )
{
// The device is an iPad running iPhone 3.2 or later.
return YES;
}
else
{
// The device is an iPhone or iPod touch.
return YES;
}
#else
// iPhone simulator
return YES;
#endif
}
#pragma mark -
#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.
NSInteger rows;
rows = [[self files] count];
return rows;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *filename = [[[self.files objectAtIndex:indexPath.row] lastPathComponent] stringByDeletingPathExtension];
NSInteger row = [indexPath row];
NSString *contentForThisRow = nil;
contentForThisRow = filename;
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
[[cell textLabel] setText:contentForThisRow];
cell.textLabel.font = [UIFont fontWithName:#"Helvetica Neue" size:90];
cell.textLabel.textColor = [UIColor blackColor];
cell.backgroundColor = [UIColor lightGrayColor];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ) {
return 80;
}
else {
return 120;
}
}
- (void)tableView:(UITableView *)tableView didUpdateFocusInContext:(UITableViewFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator
{
//this gives you the indexpath of the focused cell
NSIndexPath *nextIndexPath = [context nextFocusedIndexPath];
NSLog(#"Do Something");
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.selectedCountry = (tableView == self.tableView) ?
self.files[indexPath.row] : self.resultsTableController.filteredProducts[indexPath.row];
[self performSegueWithIdentifier:#"ShowSong" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"ShowSong"])
{
NSLog(#"Selecting %#", self.selectedCountry);
FirstViewController* userViewController = [segue destinationViewController];
userViewController.selectedCountry = self.selectedCountry;
//if you need to pass data to the next controller do it here
}
}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Relinquish ownership any cached data, images, etc. that aren't in use.
}
- (void)dealloc {
}
#end
And now the code for opening:
#implementation FirstViewController
- (CGPDFDocumentRef)openPDFLocal:(NSString *)pdfURL {
NSURL* NSUrl = [NSURL fileURLWithPath:pdfURL];
return [self openPDF:NSUrl];
}
- (CGPDFDocumentRef)openPDFURL:(NSString *)pdfURL {
NSURL* NSUrl= [NSURL URLWithString:pdfURL];
return [self openPDF:NSUrl];
}
- (CGPDFDocumentRef)openPDF:(NSURL*)NSUrl {
CFURLRef url = (CFURLRef)CFBridgingRetain(NSUrl);
CGPDFDocumentRef myDocument;
myDocument = CGPDFDocumentCreateWithURL(url);
if (myDocument == NULL) {
NSLog(#"can't open %#", NSUrl);
CFRelease (url);
return nil;
}
CFRelease (url);
if (CGPDFDocumentGetNumberOfPages(myDocument) == 0) {
CGPDFDocumentRelease(myDocument);
return nil;
}
return myDocument;
}
- (void)drawDocument:(CGPDFDocumentRef)pdfDocument
{
// Get the total number of pages for the whole PDF document
int totalPages= (int)CGPDFDocumentGetNumberOfPages(pdfDocument);
self.pages = totalPages;
NSMutableArray *pageImages = [[NSMutableArray alloc] init];
// Iterate through the pages and add each page image to an array
for (int i = 1; i <= totalPages; i++) {
// Get the first page of the PDF document
CGPDFPageRef page = CGPDFDocumentGetPage(pdfDocument, i);
CGRect pageRect = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
// Begin the image context with the page size
// Also get the grapgics context that we will draw to
UIGraphicsBeginImageContext(pageRect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
// Rotate the page, so it displays correctly
CGContextTranslateCTM(context, 0.0, pageRect.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextConcatCTM(context, CGPDFPageGetDrawingTransform(page, kCGPDFMediaBox, pageRect, 0, true));
// Draw to the graphics context
CGContextDrawPDFPage(context, page);
// Get an image of the graphics context
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[pageImages addObject:image];
}
// Set the image of the PDF to the current view
[self addImagesToScrollView:pageImages];
}
-(void)addImagesToScrollView:(NSMutableArray*)imageArray {
int heigth = 0;
for (UIImage *image in imageArray) {
UIImageView *imgView = [[UIImageView alloc] initWithImage:image];
imgView.frame=CGRectMake(200, heigth, 1520, 1080);
[_scrollView addSubview:imgView];
heigth += imgView.frame.size.height;
}
}
-(void)viewDidLayoutSubviews {
NSLog(#"%ld", (long)self.pages);
_scrollView.contentSize = CGSizeMake(1920, 1080*self.pages);
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"DOCUMENTS%#", self.selectedCountry);
NSString *testing = [self.selectedCountry stringByAppendingString:#".pdf"];
//This is passed in from a tableview after selecting the PDF needed.
_scrollView.panGestureRecognizer.allowedTouchTypes = #[ #(UITouchTypeIndirect) ];
NSString *Documents = [[NSBundle mainBundle] pathForResource:self.selectedCountry ofType:#"pdf" inDirectory:#"AIMPDF"];
NSLog(#"OKOKOK%#", Documents);
NSURL *url = [NSURL fileURLWithPath:Documents];
self.view.backgroundColor = [UIColor blackColor];
CGPDFDocumentRef pdfDocument = [self openPDF:url];
[self drawDocument:pdfDocument];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end

In your case the searching view controller stays on the top level of your app that's why the app is closed by pressing Menu button instead of returning to your start screen. On tvOS you should not use UISearchController directly and call
[self.searchController.searchBar becomeFirstResponder]; or self.searchController.active = YES; to present searching because it breaks a stacked view hierarchy that allows you to navigate upper by presented view controllers.
On Apple TV, people typically navigate by moving through stacked screens of content. Each screen may present entry points to other screens, and provides a way — through the remote — to return to the previous screen or main menu.
https://developer.apple.com/design/human-interface-guidelines/tvos/app-architecture/navigation/
There is UISearchContainerViewController view controller that manages the presentation of search results in your interface and you can use it for searching:
In tvOS, rather than push a UISearchController onto a navigation controller’s stack or use one as a child of another container view controller, embed an instance of this class and let it manage the presentation of the search controller’s content. https://developer.apple.com/documentation/uikit/uisearchcontainerviewcontroller
For instance:
UITableViewController* searchTableViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"SearchTableViewController"];
UISearchController* searchController = [[UISearchController alloc] initWithSearchResultsController:searchTableViewController];
searchController.delegate = self;
searchController.searchResultsUpdater = self;
searchController.searchBar.delegate = self;
self.searchContainerViewController = [[UISearchContainerViewController alloc] initWithSearchController:searchController];
// Show searching
[self presentViewController:self.searchContainerViewController animated:YES completion:nil];

Related

Parse search table not returning correct results

I am using parse as back-end for my app. I have found a few different methods to implement searchbar feature using a Parse tableview. This idea I found from Parse archives shows all objects on initial view and refresh, but when I search it does not return the correct results. If I type one letter "a" it returns some objects containing "a" but if I type more letters or and actual word that I know should be found it returns a blank table. It is also giving a warning when searching: A long-running Parse operation is being executed on the main thread. I have been working and researching this for a few weeks and can't get past this point. See code for implementation file.
#import "RecipeBookViewController.h"
#import "SearchedResultCell.h"
#import "RecipeDetailViewController.h"
#import "HotelViewController.h"
#import "Recipe.h"
static NSString *const NothingFoundCellIdentifier = #"NothingFoundCell";
#interface RecipeBookViewController ()
#end
#implementation RecipeBookViewController {
}
#synthesize searchedBar;
#synthesize searchResults;
#synthesize recipesTable;
- (id)initWithCoder:(NSCoder *)aCoder
{
self = [super initWithCoder:aCoder];
if (self) {
// Custom the table
// The className to query on
self.parseClassName = #"Recipe";
// The key of the PFObject to display in the label of the default cell style
self.textKey = #"name";
// Whether the built-in pull-to-refresh is enabled
self.pullToRefreshEnabled = YES;
// Whether the built-in pagination is enabled
self.paginationEnabled = NO;
// The number of objects to show per page
//self.objectsPerPage = 10;
}
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 - UIViewController
- (void)viewDidLoad
{
[super viewDidLoad];
UINib *cellNib = [UINib nibWithNibName:NothingFoundCellIdentifier bundle:nil];
[self.tableView registerNib:cellNib forCellReuseIdentifier:NothingFoundCellIdentifier];
[self.searchedBar becomeFirstResponder];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(refreshTable:)
name:#"refreshTable"
object:nil];
}
- (void)refreshTable:(NSNotification *) notification
{
// Reload the recipes
[self loadObjects];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"refreshTable" object:nil];
}
#pragma mark - UISearchBarDelegate
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[searchResults removeAllObjects];
[self.searchedBar resignFirstResponder];
searchResults = [NSMutableArray arrayWithCapacity:10];
//#warning Put your ClassName here
PFQuery *query = [PFQuery queryWithClassName:#"Recipe"];
//#warning put key that you want to search here
[query whereKey:#"name" containsString:searchedBar.text];
NSArray *results = [query findObjects];
[searchResults addObjectsFromArray:results];
//#warning put your key here
[query orderByAscending:#"name"];
//[self queryForTable];
[self loadObjects];
}
#pragma mark - PFQueryTableViewController
- (void)objectsWillLoad {
[super objectsWillLoad];
// This method is called before a PFQuery is fired to get more objects
}
- (void) objectsDidLoad:(NSError *)error
{
[super objectsDidLoad:error];
NSLog(#"error: %#", [error localizedDescription]);
}
#pragma mark - Query
- (PFQuery *)queryForTable
{
PFQuery *query;
if (self.searchResults == 0) {
query = [PFQuery queryWithClassName:self.parseClassName];
} else {
query = [PFQuery queryWithClassName:self.parseClassName];
NSString *searchThis = [searchedBar.text lowercaseString];
//#warning key you wanted to search here
[query whereKeyExists:#"name"];
[query whereKey:#"name" containsString:searchThis];
}
[query orderByAscending:#"name"];
// If Pull To Refresh is enabled, query against the network by default.
if (self.pullToRefreshEnabled) {
query.cachePolicy = kPFCachePolicyNetworkOnly;
}
// If no objects are loaded in memory, we look to the cache first to fill the table
// and then subsequently do a query against the network.
if (self.objects.count == 0) {
query.cachePolicy = kPFCachePolicyCacheThenNetwork;
}
return query;
}
/*
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section
{
if (searchResults == nil) {
return 0;
} else if ([searchResults count] == 0) {
return 1;
} else {
return [self.objects count];
}
}
*/
// Override to customize the look of a cell representing an object. The default is to display
// a UITableViewCellStyleDefault style cell with the label being the first key in the object.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath object:(PFObject *)object
{
static NSString *simpleTableIdentifier = #"RecipeCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
// Configure the cell
PFFile *thumbnail = [object objectForKey:#"imageFile"];
PFImageView *thumbnailImageView = (PFImageView*)[cell viewWithTag:100];
thumbnailImageView.image = [UIImage imageNamed:#"recipeBoxImage2.jpg"];
thumbnailImageView.file = thumbnail;
[thumbnailImageView loadInBackground];
UILabel *nameLabel = (UILabel*) [cell viewWithTag:101];
nameLabel.text = [object objectForKey:#"name"];
UILabel *prepTimeLabel = (UILabel*) [cell viewWithTag:102];
prepTimeLabel.text = [object objectForKey:#"prepTime"];
static NSString *LoadMoreCellIdentifier = #"LoadMoreCell";
UITableViewCell *loadcell = [self.tableView dequeueReusableCellWithIdentifier:LoadMoreCellIdentifier];
if (!cell) {
loadcell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:LoadMoreCellIdentifier];
}
return cell;
}
- (void)configureSearchResult:(SearchedResultCell *)cell atIndexPath: (NSIndexPath *)indexPath object:(PFObject *)object
{
static NSString *simpleTableIdentifier = #"RecipeCell";
SearchedResultCell *searchcell = [self.tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (searchcell == nil) {
searchcell = [[SearchedResultCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
// Configure the cell
PFFile *thumbnail = [object objectForKey:#"imageFile"];
PFImageView *thumbnailImageView = (PFImageView*)[cell viewWithTag:100];
thumbnailImageView.image = [UIImage imageNamed:#"recipeBoxImage2.jpg"];
thumbnailImageView.file = thumbnail;
[thumbnailImageView loadInBackground];
UILabel *nameLabel = (UILabel*) [cell viewWithTag:101];
nameLabel.text = [object objectForKey:#"name"];
UILabel *prepTimeLabel = (UILabel*) [cell viewWithTag:102];
prepTimeLabel.text = [object objectForKey:#"prepTime"];
}
// Set CellForRowAtIndexPath
- (UITableViewCell *)searchtableView:(UITableView *)searchtableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{
static NSString *CellIdentifier = #"SearchResultCell";
//Custom Cell
SearchedResultCell *cell = [searchtableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[SearchedResultCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if ([searchResults count] == 0) {
//cell.mainTitle.text = #"Nothing Found";
return [self.tableView dequeueReusableCellWithIdentifier:NothingFoundCellIdentifier];
} else {
//#warning put your ClassName here
PFObject *object = [PFObject objectWithClassName:#"Recipe"];
object = [searchResults objectAtIndex:indexPath.row];
[self configureSearchResult:cell atIndexPath:indexPath object:object];
//[self configureSearchResult:cell atIndexPath:indexPath object:object];
return cell;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForNextPageAtIndexPath:(NSIndexPath *)indexPath {
static NSString *LoadMoreCellIdentifier = #"LoadMoreCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:LoadMoreCellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:LoadMoreCellIdentifier];
}
return cell;
}
//// Set TableView Height for Load Next Page
//- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath *)indexPath {
// if([self.objects count] == indexPath.row) {
// // Load More Cell Height
// return 60.0;
// } else {
// return 80.0;
// }
//}
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[searchedBar resignFirstResponder];
if ([self.objects count] == indexPath.row) {
[self loadNextPage];
} else {
PFObject *photo = [self.objects objectAtIndex:indexPath.row];
NSLog(#"%#", photo);
// Do something you want after selected the cell
}
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
[self.searchedBar resignFirstResponder];
}
//- (void)tableView:(UITableView *)tableView commitEditingStyle: (UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
//{
// // Remove the row from data model
// PFObject *object = [self.objects objectAtIndex:indexPath.row];
// [object deleteInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
// [self refreshTable:nil];
// }];
//}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showRecipeDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
RecipeDetailViewController *destViewController = segue.destinationViewController;
PFObject *object = [self.objects objectAtIndex:indexPath.row];
Recipe *recipe = [[Recipe alloc] init];
recipe.name = [object objectForKey:#"name"];
recipe.imageFile = [object objectForKey:#"imageFile"];
recipe.prepTime = [object objectForKey:#"prepTime"];
recipe.ingredients = [object objectForKey:#"ingredients"];
recipe.instructions = [object objectForKey:#"instructions"];
recipe.servings = [object objectForKey:#"servings"];
recipe.hotelSite = [object objectForKey:#"hotelSite"];
recipe.recipeType = [object objectForKey:#"recipeType"];
destViewController.recipe = recipe;
}
}
#end
found this - hope it helps others - credit to Bizzi-Body
https://github.com/Bizzi-Body/ParseTutorial-Part-2
//
// GourmetChefViewController.m
//
// Created by RedMac on 3/19/15.
//
#import "RecipeBookViewController.h"
#interface RecipeBookViewController ()
{
NSMutableArray *totalStrings;
NSMutableArray *filteredStrings;
BOOL isFiltered;
}
#end
#implementation RecipeBookViewController
#pragma mark -
#pragma mark UIViewController
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
self.mySearchBar.delegate =self;
self.myTableView.delegate = self;
self.myTableView.dataSource=self;
[self retrieveFromParse];
}
- (void) retrieveFromParse {
PFQuery *retrieveRecipes = [PFQuery queryWithClassName:#"Recipe"];
[retrieveRecipes whereKeyExists:#"name"];
[retrieveRecipes findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
NSLog(#"%#", objects);
totalStrings = [[NSMutableArray alloc] initWithArray:objects];
}
[self.myTableView reloadData];
}];
}
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *) searchText{
if (searchText.length ==0){
isFiltered =NO;}
else{
isFiltered =YES;
filteredStrings=[[NSMutableArray alloc]init];
for(PFObject *element in totalStrings) {
NSString * str = [element objectForKey:#"name"];
NSLog(#"%#", NSStringFromClass([element class])); // you thought that totalStrings
// contained NSString objects,
// but it contains PFObjects.
NSRange stringRange =[str rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (stringRange.location !=NSNotFound) {
// you need to add the PFObject back to make your cellForRowAtIndexPath: method
// work.
[filteredStrings addObject:element]; // used to be :str
}
}
}
[self.myTableView reloadData];
}
//table view datasource and delegate method.....
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger) section
{
if (isFiltered){
return [filteredStrings count];
}return [totalStrings count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"RecipeCell";
UITableViewCell *cell= [tableView dequeueReusableCellWithIdentifier: CellIdentifier];
if (!cell){
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if(!isFiltered){
PFObject *tempObject =[totalStrings objectAtIndex: indexPath.row];
cell.textLabel.text = [tempObject objectForKey:#"name"];
}
else
{
PFObject *tempObject2 =[filteredStrings objectAtIndex: indexPath.row];
cell.textLabel.text =[tempObject2 objectForKey:#"name"];
}
return cell;
}
- (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.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end

UITableView reloadData lose elements from cell

I have a UITableView and his datasource is an NSMutableArray declared in my interface:
#property (strong, nonatomic) NSMutableArray *arrElements;
Now I implemented a simple "load more" in this way:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
float endScrolling = scrollView.contentOffset.y + scrollView.frame.size.height;
if (endScrolling >= scrollView.contentSize.height)
{
//only if i have others results i will call load more
if([self.items_amount integerValue] > self.arrElements.count) {
if(DEBUG_MODE == 1) {
NSLog(#"Load more");
}
//get start param from array size and call load more
NSNumber *start = [NSNumber numberWithInteger:([self.arrElements count]+1)];
NSArray *passParams = [NSArray arrayWithObjects:self.menuItem,start,[NSNumber numberWithInteger:NUM_RESULTS_FOR_PAGE], nil];
[self performSelector:#selector(loadMore:) withObject:passParams afterDelay:0.1];
}
}
}
and this is my loadMore method:
//load more elements
- (void)loadMore:(NSArray *)arrParams {
//(MenuItem *)menuItem startingFrom:(NSNumber *)start numResults:(NSNumber *)results;
MenuItem *menuItem = [arrParams objectAtIndex:0];
NSNumber *start = [arrParams objectAtIndex:1];
NSNumber *results = [arrParams objectAtIndex:2];
if(DEBUG_MODE == 1) {
NSLog(#"Before load more %lu", (unsigned long)[self.arrElements count]);
}
//call API and parse it
WebServicesClient *restClient = [[WebServicesClient alloc] init];
NSData *data = [restClient callWorkAPI:[menuItem pathAPI] inLanguage:[[NSLocale preferredLanguages] objectAtIndex:0] withLat:self.latitude withLng:self.longitude startingFrom:start numRows:results];
for(Work* work in [[restClient parseWorks:data] objectForKey:#"items"]) {
[self.arrElements addObject:work];
}
if(DEBUG_MODE == 1) {
NSLog(#"After load more %lu", (unsigned long)[self.arrElements count]);
}
[self.tableElem reloadData];
}
And this is my custom cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier;
CellIdentifier = #"HomeCell";
HomeCell *cell = (HomeCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(!cell) {
cell = [[HomeCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Work *work = (Work *)[[self arrElements] objectAtIndex:indexPath.row];
cell.backgroundColor = [UIColor clearColor];
cell.labelTitleItem.text = [work title];
cell.labelSubtitleItem.text = #"my category"
//if exists image
if([[work image] isKindOfClass:[NSString class]] && [[work image] length] > 0) {
dispatch_async(dispatch_get_global_queue(0,0), ^{
NSData * data = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:[work image]]];
if ( data == nil )
return;
dispatch_async(dispatch_get_main_queue(), ^{
cell.imageItem.image = [UIImage imageWithData: data];
});
});
} else {
//remove image setting height to 0
[cell.imageItem setFrame:CGRectMake(cell.imageItem.frame.origin.x, cell.imageItem.frame.origin.y, cell.imageItem.frame.size.width, 0)];
}
if([[work distance] isKindOfClass:[NSString class]]) {
[cell.imagePriority setBackgroundColor:[UIColor lightGrayColor]];
cell.labelDistanceItem.text = [self convertDistance:[work distance]];
cell.labelDistanceItem.textColor = [UIColor whiteColor];
} else {
//remove image setting height to 0
[cell.imagePriority setFrame:CGRectMake(cell.imagePriority.frame.origin.x, cell.imagePriority.frame.origin.y, cell.imagePriority.frame.size.width, 0)];
//remove label distance setting height to 0
[cell.labelSubtitleItem setFrame:CGRectMake(cell.labelSubtitleItem.frame.origin.x, cell.labelSubtitleItem.frame.origin.y, cell.labelSubtitleItem.frame.size.width, 0)];
}
return cell;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[self arrElements] count];
}
Now the problem is that after reloadData i lose the text of a UILabel (my category) of my CustomCell
please, Any suggests?
I've had similar problems with TalbeViews. Try using the method
- (void) tableView:(UITableView *)tableView willDisplayCell:(RCGameTableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
to add the elements that you want. Keep the cell initialization that you do at the beginning of cellForRowAtIndexPath, but then return the cell right after and set the background color, labels, images, etc. in the willDisplayCell delegate function I mentioned.

pushViewController:detail not pushing detailView

I had my app navigating views perfectly. Now, for some reason that I can't figure out, my detailView is not presenting on the pushViewController:detail method in my modal view.
I cannot figure out why it's not working any more. Any help would be appreciated. Thanks.
Here's the method:
- (void)tableView:(UITableView *)tView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tView deselectRowAtIndexPath:indexPath animated:YES];
if(indexPath.row == 0){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 1){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 2){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 3){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 4){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
}
Here's the class code. I'm not sure if I need to pass in a navigationController with modalView:
//
// ModalView.m
// DiningLog
//
// Created by Eric Rea on 10/10/11.
// Copyright 2011 Avid. All rights reserved.
//
#import "ModalView.h"
#import "DetailView.h"
#implementation ModalView
#synthesize tableView, excersizeName, numSets, time, restTime, dateFormatter, rating, excersizeArray, plistArray, numberWithBool;
-(IBAction) cancel:(id)sender{
[self dismissModalViewControllerAnimated:YES];
}
-(IBAction) save:(id)sender{
// get paths from root direcory
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
// get documents path
NSString *documentsPath = [paths objectAtIndex:0];
// get the path to our Data/plist file
NSString *plistPath = [documentsPath stringByAppendingPathComponent:#"ExcersizeList.plist"];
// check to see if Data.plist exists in documents
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath])
{
// if not in documents, get property list from main bundle
plistPath = [[NSBundle mainBundle] pathForResource:#"Excersizes" ofType:#"plist"];
}
// read property list into memory as an NSData object
NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
NSString *errorDesc = nil;
NSPropertyListFormat format;
// convert static property list into dictionary object
NSDictionary *temp = (NSDictionary *)[NSPropertyListSerialization propertyListFromData:plistXML mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&errorDesc];
if (!temp)
{
NSLog(#"Error reading plist: %#, format: %d", errorDesc, format);
}
// assign values
self.plistArray = [NSMutableArray arrayWithArray:[temp objectForKey:#"Excersizes"]];
NSLog(#"The contents of plistArray is%#", plistArray);
// set the variables to the values in the text fields
self.excersizeArray = [[NSMutableArray alloc] initWithCapacity:4];
[excersizeArray addObject:excersizeName];
[excersizeArray addObject:numSets];
[excersizeArray addObject:time];
[excersizeArray addObject:restTime];
[plistArray addObject:excersizeArray];
// create dictionary with values in UITextFields
NSDictionary *plistDict = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects: plistArray, nil] forKeys:[NSArray arrayWithObjects: #"Excersizes", nil]];
NSString *error = nil;
// create NSData from dictionary
// NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:plistDict format:NSPropertyListXMLFormat_v1_0 errorDescription:&error];
// check is plistData exists
if(plistDict)
{
// write plistData to our Data.plist file
[plistDict writeToFile:plistPath atomically:YES];
}
else
{
NSLog(#"Error in saveData: %#", error);
[error release];
}
[self dismissModalViewControllerAnimated:YES];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tView {
// Return the number of sections.
return 1;
}
-(void)setObject:(id)object forNum:(int)num{
if(num == 0){
self.excersizeName = object;
NSLog(#"res %#", self.excersizeName);
}else if(num == 1){
self.numSets = object;
NSLog(#"res %#", self.numSets);
}else if(num == 2){
self.time = object;
NSLog(#"res %#", self.time);
}else if(num == 3){
self.restTime = object;
NSLog(#"res %#", self.restTime);
}else if(num == 4){
self.rating = [object floatValue];
}
[tableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return 5;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:CellIdentifier] autorelease];
}
if(indexPath.row == 0){
cell.textLabel.text = #"Excersize";
cell.detailTextLabel.text = excersizeName;
}
if(indexPath.row == 1){
cell.textLabel.text = #"Sets";
cell.detailTextLabel.text = numSets;
}
if(indexPath.row == 2){
cell.textLabel.text = #"Time";
cell.detailTextLabel.text = time;
}
if(indexPath.row == 3){
cell.textLabel.text = #"Rest";
cell.detailTextLabel.text = restTime;
}
if(indexPath.row == 4){
cell.textLabel.text = #"Rating";
cell.detailTextLabel.text = [NSString stringWithFormat:#"%f",rating];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
- (NSDateFormatter *)dateFormatter {
if (dateFormatter == nil) {
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterNoStyle];
}
return dateFormatter;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tView deselectRowAtIndexPath:indexPath animated:YES];
if(indexPath.row == 0){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 1){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 2){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 3){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 4){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
}
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
/*
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization.
}
return self;
}
*/
/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
}
*/
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations.
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
- (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.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
#end
Have you debugged and checked that your navigationController isn't nil ?
I figured it out. I accidentally erased the method insertNewObject in my rootViewController. When I rewrote it, I forgot to add in ModalView * modal = [[ModalView alloc] init];. That was the problem.
Here's what the method looks like now that it's working:
- (void)insertNewObject {
ModalView * modal = [[ModalView alloc] init];
UINavigationController *controller = [[UINavigationController alloc] initWithRootViewController:modal];
[self presentModalViewController:controller animated:YES];
}

Invalid argument type to unary expression

I have this program with a tableView as my first view. I have also implemented (or at least tried to) a search bar on top of the view. Have used several hours to search for a solution, but without positive results.
#import "FirstViewController.h"
#import "NSDictionary-MutableDeepCopy.h"
#implementation FirstViewController
#synthesize listData, table, search, allNames, names, keys;
#pragma mark -
#pragma mark Custom Methods
- (void)resetSearch {
NSMutableDictionary *allNamesCopy = [self.allNames mutableDeepCopy];
self.names = allNamesCopy;
[allNamesCopy release];
NSMutableArray *keyArray = [[NSMutableArray alloc] init];
[keyArray addObjectsFromArray:[[self.allNames allKeys]
sortedArrayUsingSelector:#selector(compare:)]];
self.keys = keyArray;
[keyArray release];
}
-(void)handleSearchForTerm:(NSString *)searchTerm {
NSMutableArray *sectionsToRemove = [[NSMutableArray alloc] init];
[self resetSearch];
for (NSString *key in self.keys) {
NSMutableArray *array = [names valueForKey:key];
NSMutableArray *toRemove = [[NSMutableArray alloc] init];
for (NSString *name in listData) {
if ([name rangeOfString:searchTerm
options:NSCaseInsensitiveSearch].location == NSNotFound)
[toRemove addObject:name];
}
if ([array count] == [toRemove count])
[sectionsToRemove addObject:key];
[array removeObjectsInArray:toRemove];
[toRemove release];
}
[self.keys removeObjectsInArray:sectionsToRemove];
[sectionsToRemove release];
[table reloadData];
}
- (void)viewDidLoad {
NSString *path = [[NSBundle mainBundle] pathForResource:#"sortednames" ofType:#"plist"];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
self.names = dict;
self.allNames = dict;
[dict release];
[self resetSearch];
[table reloadData];
[table setContentOffset:CGPointMake(0.0, 44.0)animated:NO];
self.parentViewController.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"background.png"]];
NSArray *array = [[NSArray alloc] initWithObjects:
// A larger amount of objects here.
self.listData = array;
[array release];
[super viewDidLoad];
}
/*
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
// Custom initialization
}
return self;
}
*/
/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/
/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
}
*/
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
- (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.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.listData = nil;
self.table = nil;
self.search = nil;
self.allNames = nil;
self.names = nil;
self.keys = nil;
}
- (void)dealloc {
[listData release];
[search release];
[table release];
[allNames release];
[keys release];
[names release];
[super dealloc];
}
#pragma mark -
#pragma mark Table View Data Source Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return ([keys count] > 0) ? [keys count] : 1;
}
- (NSInteger)tableView:(UITableView *)aTableView
numberOfRowsInSection: (NSInteger)section {
return [self.listData count];
if ([keys count] == 0)
return 0;
NSString *key = [keys objectAtIndex:section];
NSArray *nameSection = [names objectForKey:key];
return [nameSection count];
}
- (UITableViewCell *) extracted_method: (UITableViewCell *) cell {
return cell;
}
- (UITableViewCell *)tableView:(UITableView *)aTableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSString *key = [keys objectAtIndex:section];
NSArray *nameSection = [names objectForKey:key];
static NSString *sectionsTableIdentifier = #"sectionsTableIdentifier";
UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:
sectionsTableIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier: sectionsTableIdentifier] autorelease];
}
cell.backgroundColor = [UIColor clearColor];
cell.textColor = [UIColor whiteColor];
cell.detailTextLabel.textColor = [UIColor whiteColor];
cell.text = [nameSection objectAtIndex:row];
[self extracted_method: cell].text = [listData objectAtIndex:row];
return cell;
}
- (NSString *)tableView:(UITableView *)tableView
titleForHeaderInSection:(NSInteger)section {
if ([keys count] == 0)
return nil;
NSString *key = [keys objectAtIndex:section];
return key;
}
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return keys;
}
#pragma mark -
#pragma mark Table View Delegate Methods
- (NSIndexPath *)tableView:(UITableView *)tableView
willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[search resignFirstResponder];
return indexPath;
}
#pragma mark -
#pragma mark Search Bar Delegate Methods
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
NSString *searchTerm = [searchBar text];
[self handleSearchForTerm:searchTerm];
}
- (void)searchBar:(UISearchBar *)searchBar
textDidChange:(NSString *)searchTerm {
if ([searchTerm length] == 0) {
[self resetSearch];
[table reloadData];
return;
}
[self handleSearchForTerm:searchTerm];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
search.text = #"";
[self resetSearch];
[table reloadData];
[searchBar resignFirstResponder];
}
#end
Ok guys. My problem is that this doesnt get the search function to work. In addition I receive siginal SIGABRT at this line:
NSString *key = [keys objectAtIndex:section];
So I need help with two things:
1: I need to get that SIGABRT away.
Error log message: * Terminating app due to uncaught exception
'NSRangeException', reason: '* -[NSMutableArray objectAtIndex:]:
index 0 beyond bounds for empty array'
That is I don't store any data in keys. how would I do that? and what would I store?
2: Want the search function to search in my listData array!
Thanks in advance - hope u can help!
You have not finished your sectionIndexTitlesForTableView: method. Right now it is:
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return keys;
There is no closing }, so the compiler thinks everything after that is still part of that method. When you try to define the next method, use use - (NSIndexPath *) to indicate that it is an instance method which returns NSIndexPath*, but the compiler thinks you are trying to subtract something.
The solution is simple: Add the } to the end of sectionIndexTitlesForTableView:.
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return keys;
}

pickerview app crashing due to NSRangeException NSCFArray objectAtIndex: index (5)...beyond bounds (5)

Once again working through beginning iphone development and I am putting together a bunch of UIPicker type apps, the last one of which is a slot machine type of game, super simple. Anyway I am not really understanding why this error is coming up. to my understanding the picker view is asking its delegate for an object in the array that is past the range available to that array.
That being said I have no idea why it is doing this or how to fix it, any help would be appreciated, heres the code from the particular .m file( get the full project here: http://files.me.com/knyck2/89q3w3 ):
//
// CustomPickerViewController.m
// Pickers
//
// Created by Nicholas Iannone on 1/29/10.
// Copyright 2010 Apple Inc. All rights reserved.
//
#import "CustomPickerViewController.h"
#implementation CustomPickerViewController
#synthesize column1, column2, column3, column4, column5, picker, winLabel;
-(IBAction) spin : (id) sender {
NSLog(#"even got here");
BOOL win = NO;
int numInRow = 1;
int lastVal = -1;
for (int i = 0; 1 < 5; i++) {
int newValue = random() % [self.column1 count];
if (newValue == lastVal) {
NSLog(#"even got here");
numInRow++;
}
else
numInRow = 1;
lastVal = newValue;
[picker selectRow:newValue inComponent:i animated:YES];
[picker reloadComponent:i];
if (numInRow >= 3)
win = YES;
NSLog(#"even got here");
}
if (win)
winLabel.text = #"winner!";
else {
winLabel.text = #"";
NSLog(#"even got here");
}
}
/*
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
// Custom initialization
}
return self;
}
*/
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
UIImage *seven = [UIImage imageNamed:#"seven.png"];
UIImage *bar = [UIImage imageNamed:#"bar.png"];
UIImage *crown = [UIImage imageNamed:#"crown.png"];
UIImage *cherry = [UIImage imageNamed:#"cherry.png"];
UIImage *lemon = [UIImage imageNamed:#"lemon.png"];
UIImage *apple = [UIImage imageNamed:#"apple.png"];
for (int i = 1; i <= 5 ; i++) {
UIImageView *sevenView = [[UIImageView alloc] initWithImage: seven];
UIImageView *barView = [[UIImageView alloc] initWithImage: bar];
UIImageView *crownView = [[UIImageView alloc] initWithImage: crown];
UIImageView *cherryView = [[UIImageView alloc] initWithImage: cherry];
UIImageView *lemonView = [[UIImageView alloc] initWithImage: lemon];
UIImageView *appleView = [[UIImageView alloc] initWithImage: apple];
NSArray *imageViewArray = [[NSArray alloc] initWithObjects: sevenView, barView, crownView, cherryView, lemonView, appleView, nil];
NSString *fieldName =[[NSString alloc] initWithFormat:#"column%d", i];
[self setValue:imageViewArray forKey:fieldName];
[fieldName release];
[imageViewArray release];
[sevenView release];
[crownView release];
[barView release];
[cherryView release];
[lemonView release];
[appleView release];
}
srandom(time(NULL));
[super viewDidLoad];
}
/*
// Override to allow orientations other than the default portrait orientation.
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
- (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.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[picker release];
[winLabel release];
[column1 release];
[column2 release];
[column3 release];
[column4 release];
[column5 release];
[super dealloc];
}
#pragma mark -
#pragma mark Picker Data Source Methods
-(NSInteger) numberOfComponentsInPickerView: (UIPickerView *) pickerView {
return 5;
}
-(NSInteger) pickerView: (UIPickerView *) pickerView numberOfRowsInComponent: (NSInteger) component {
return [self.column1 count];
}
#pragma mark Picker Delegate Methods
-(UIView *) pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent: (NSInteger) component reusingView : (UIView *)view {
NSString *arrayName = [[NSString alloc] initWithFormat:#"column%d", component + 1];
NSArray *array = [self valueForKey:arrayName];
NSLog(#"got here yo");
return [array objectAtIndex: row];
NSLog(#"holyshit");
}
#end
The reason why it's breaking is this loop. Take a look at your for loop condition:
1 < 5. Yes, 1 is always less than 5. This means that you have an infinite loop. I'm sure you meant i < 5.
for (int i = 0; 1 < 5; i++) {
int newValue = random() % [self.column1 count];
if (newValue == lastVal) {
NSLog(#"even got here");
numInRow++;
}
else
numInRow = 1;
lastVal = newValue;
[picker selectRow:newValue inComponent:i animated:YES];
[picker reloadComponent:i];
if (numInRow >= 3)
win = YES;
NSLog(#"even got here");
}
You're testing if 1 < 5, which is always true. You want i < 5.