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];
}
Related
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];
I have a simple view which has been successfully loading a table of data from CoreData for the last 18 months. It even works now on devices that have been upgraded to IOS 7. But when I upgraded to Xcode5 and run through the IOS7 3.5inch retina simulator my table is always empty. I have pasted my code below and I can confirm that the fetchRequests are returning the data because I can see this in the NSLog outputs. But why has be table stopped populating the cells?
I feel really stupid because I just cannot figure this one out…
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"listData count in numberOFRowsInSection is: %i", listData.count);
return [self.listData count];
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
Sessions *info = [_fetchedResultsController objectAtIndexPath:indexPath];
NSLog(#"info content is: %#", info.sport);
//Format cell data ready to be displayed
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"EE, dd LLL yyyy"];
NSString *dateString = [dateFormat stringFromDate:info.date];
NSNumber *dist1Nbr = info.dist1;
int dist1Int = [dist1Nbr integerValue];
float distIntKorM = ([dist1Nbr integerValue])/1000;
NSString *dist1StrMeters = [[NSString alloc] initWithFormat:#"%i", dist1Int];
NSString *dist1StrKorM = [[NSString alloc] initWithFormat:#"%.01f", distIntKorM];
//Select image to display
if ([info.sport isEqualToString:#"Run"]) {
UIImage *image = [UIImage imageNamed:#"trainers-15x10.png"];
cell.imageView.image = image;
cell.textLabel.text = [[NSString alloc] initWithFormat:#"%#: (%#),", dateString, info.sport];
cell.detailTextLabel.text = [[NSString alloc] initWithFormat:#"Type: %#, Dist: %#", info.sessiontype, dist1StrKorM];
NSLog(#"Cell text for Runs shoudl be: %#", cell.textLabel.text);
} else if ([info.sport isEqualToString:#"Other"]) {
UIImage *image = [UIImage imageNamed:#"weights-15x10.png"];
cell.imageView.image = image;
cell.textLabel.text = [[NSString alloc] initWithFormat:#"%#: (%#),", dateString, info.sport];
cell.detailTextLabel.text = [[NSString alloc] initWithFormat:#"Type: %#, Dist: %#", info.sessiontype, dist1StrKorM];
} else if ([info.sport isEqualToString:#"Swim"]) {
UIImage *image = [UIImage imageNamed:#"goggles-15x10.png"];
cell.imageView.image = image;
cell.textLabel.text = [[NSString alloc] initWithFormat:#"%#: (%#),", dateString, info.sport];
cell.detailTextLabel.text = [[NSString alloc] initWithFormat:#"Type: %#, Dist: %#m", info.sessiontype, dist1StrMeters];
NSLog(#"Cell text for Swims shoudl be: %#", cell.textLabel.text);
} else if ([info.sport isEqualToString:#"Cycle"]) {
UIImage *image = [UIImage imageNamed:#"bike-15x10.png"];
cell.imageView.image = image;
cell.textLabel.text = [[NSString alloc] initWithFormat:#"%#: (%#),", dateString, info.sport];
cell.detailTextLabel.text = [[NSString alloc] initWithFormat:#"Type: %#, Dist: %#", info.sessiontype, dist1StrKorM];
} else if ([info.sport isEqualToString:#"Brick"]) {
UIImage *image = [UIImage imageNamed:#"brick-15x10.png"];
cell.imageView.image = image;
cell.textLabel.text = [[NSString alloc] initWithFormat:#"%#: (%#),", dateString, info.sport];
cell.detailTextLabel.text = [[NSString alloc] initWithFormat:#"Type: %#, Dist: %#", info.sessiontype, dist1StrKorM];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"editSession";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// this cell backgrond colour alternating works!
UIView *bgColor = [cell viewWithTag:100];
if (!bgColor) {
CGRect frame = CGRectMake(0, 0, 320, 50);
bgColor = [[UIView alloc] initWithFrame:frame];
bgColor.tag = 100;
[cell addSubview:bgColor];
[cell sendSubviewToBack:bgColor];
}
if (indexPath.row % 2 == 0) {
bgColor.backgroundColor = [UIColor colorWithRed:233.0/255.0 green:233.0/255.0 blue:233.0/255.0 alpha:1.0];
} else {
bgColor.backgroundColor = [UIColor clearColor]; }
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
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)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
if (_context == nil)
{
_context = [(SGK_T4T_01AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSLog(#"After managedObjectContext: %#", _context);
}
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1);
} else {
NSLog(#"After fetchedResultsController: %#", _fetchedResultsController);
//NSLog(#"After managedObjectContext: %#", _fetchedResultsController);
}
self.title = #"Sessions";
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
[self setListData:nil];
[self setSelectedSession:nil];
[self setSessionSport:nil];
//[self setRecordCount:nil];
[self setFetchedResultsController:nil];
[self setContext:nil];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
SGK_T4T_01AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSEntityDescription *entityDiscription = [NSEntityDescription entityForName:#"Sessions" inManagedObjectContext:context];
//NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"refid" ascending:YES];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDiscription];
NSError *error;
NSArray *objects = [context executeFetchRequest:request error:&error];
if (objects == nil) {
NSLog(#"The fetch request returned an array == nil");
} else {
NSLog(#"The fetch request returned an array!!!");
NSLog(#"objects contents is: %#", objects);
NSLog(#"objects count = %i", [objects count]);
listData = objects;
NSLog(#"listData count = %i", [listData count]);
//NSUInteger *recordCount = [objects count];
recordCount = [objects count];
}
//reload tableView:dataSource from CoreData when view reappears...
if (_context == nil)
{
_context = [(SGK_T4T_01AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSLog(#"After managedObjectContext: %#", _context);
}
NSError *error1;
if (![[self fetchedResultsController] performFetch:&error1]) {
NSLog(#"Unresolved error %#, %#", error1, [error1 userInfo]);
exit(-1);
} else {
NSLog(#"viewWillAppear: fetchedResultsController: %#", _fetchedResultsController);
}
//end of reload tableView:dataSource from CoreData when view reappears...
[self.tableView reloadData];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
//[self setFetchedResultsController:nil];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
//[self setFetchedResultsController:nil];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
//#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[_context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];
NSError *error = nil;
if (![_context save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
} 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
}
[self.tableView reloadData];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
if (type == NSFetchedResultsChangeDelete) {
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
NSUInteger index = indexPath.row;
//NSLog(#" Prep4Seg indexPath.row = %u", index);
//NSLog(#" Prep4Seg recordCount = %u", recordCount);
/*
Subtract the row index from the row count to get the correct position in the Array (because I am sorting on date order so tableCell position 0 is position 2 in the Array (if there are 3 only items in the table and array) so if you don't invert the indexPath you end up passing the last item instead of the first or second last item instead of the second and so on...
*/
NSUInteger arrayIndex = (recordCount-index-1);
//NSLog(#" Prep4Seg arrayIndex = %u", arrayIndex);
selectedSession = [listData objectAtIndex:arrayIndex];
//NSLog(#"listData = %#", listData);
//NSLog(#"SelectedSession = %#", selectedSession);
NSNumber *refId = [selectedSession valueForKey:#"refid"];
NSString *refIdToSend = [[NSString alloc] initWithFormat:#"%#", refId];
NSLog(#"Prep4Seg in tableView: refIdToSend = %#", refIdToSend);
if ([segue.identifier isEqualToString:#"editSession"]) {
SGK_T4T_EditSessionDetail *editSessionDetail = segue.destinationViewController;
editSessionDetail.delegate = (id)self;
editSessionDetail.returnFromDatePickerView = [[NSString alloc] initWithFormat:#"no"];
editSessionDetail.recedIndex = refIdToSend;
}
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller is about to start sending change notifications, so prepare the table view for updates.
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller has sent all current change notifications, so tell the table view to process all updates.
[self.tableView endUpdates];
}
And my log output is:
2013-11-09 16:04:04.034 trainForTri copy[6509:a0b] After managedObjectContext: <NSManagedObjectContext: 0xb589bc0>
2013-11-09 16:04:04.036 trainForTri copy[6509:a0b] After fetchedResultsController: <NSFetchedResultsController: 0xb5e2c40>
2013-11-09 16:04:04.040 trainForTri copy[6509:a0b] The fetch request returned an array!!!
2013-11-09 16:04:04.041 trainForTri copy[6509:a0b] objects contents is: (
"<NSManagedObject: 0xb5c8570> (entity: Sessions; id: 0xb5ac970 <x-coredata://B93EE0DE-E6FA-491C-9C8F-23692A36DD0C/Sessions/p1> ; data: <fault>)",
"<NSManagedObject: 0xb5d6320> (entity: Sessions; id: 0xb58a2a0 <x-coredata://B93EE0DE-E6FA-491C-9C8F-23692A36DD0C/Sessions/p2> ; data: <fault>)",
"<NSManagedObject: 0xb5d0370> (entity: Sessions; id: 0xb5dc270 <x-coredata://B93EE0DE-E6FA-491C-9C8F-23692A36DD0C/Sessions/p3> ; data: <fault>)",
"<NSManagedObject: 0xb5e3dd0> (entity: Sessions; id: 0xb5ebcc0 <x-coredata://B93EE0DE-E6FA-491C-9C8F-23692A36DD0C/Sessions/p4> ; data: <fault>)",
"<NSManagedObject: 0xb585e40> (entity: Sessions; id: 0xb5e4e40 <x-coredata://B93EE0DE-E6FA-491C-9C8F-23692A36DD0C/Sessions/p5> ; data: <fault>)"
)
2013-11-09 16:04:04.041 trainForTri copy[6509:a0b] objects count = 5
2013-11-09 16:04:04.042 trainForTri copy[6509:a0b] listData count = 5
2013-11-09 16:04:04.043 trainForTri copy[6509:a0b] viewWillAppear: fetchedResultsController: <NSFetchedResultsController: 0xb5a01e0>
2013-11-09 16:04:04.043 trainForTri copy[6509:a0b] listData count in numberOFRowsInSection is: 5
OK, found the issue with this. Eventually after almost wanting to throw my Macbook out of the window in frustration with Xcode5 I shut everything down and restarted. when I opened Xcode, built and ran my App it lo longer loaded an empty table - it now produced an error which indicated that there was something wrong with my NSFetchedResultsController. I traced it to an issue with the cache not clearing (or not being mutable) - so I removed the cache name and set it to nil and everything is working again. I am not sure if this is an IOS7/Xcode5 issue but it has not been a problem until this upgrade. For anyone searching for a similar fix here is the offending line of code:
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_context sectionNameKeyPath:nil cacheName:#"Root"];
And this is the version that works!
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_context sectionNameKeyPath:nil cacheName:nil];
I hope I'm not the only one ever to struggle with this and therefore just a thickie!
I have a tableview that displays a list of "favorited" items. Users favorite items in another tableview, and favorited items are listed in this tableview (FavoritesTableView.m).
For some reason, I can't get checked items (favorited items) to "uncheck" from the FavoritesTableView? What am I missing?
See the .m file below...
FavoritesViewController.h
#import <UIKit/UIKit.h>
#import "StrainTableCell.h"
#interface FavoritesViewController : UITableViewController
{
}
#property (strong, nonatomic) NSArray *favoritesArrayset;
#property (strong, nonatomic) IBOutlet UITableView *favoritesTable;
#property (nonatomic, strong) NSMutableArray * favoritesArray;
- (IBAction)backbuttonpressed: (UIBarButtonItem *)sender;
#end
FavoritesViewController.m
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
if (favoritesArray == Nil)
{
favoritesArray = [[NSMutableArray alloc] init];
}
else
{
[favoritesArray removeAllObjects];
}
NSData *dataSave = [[NSUserDefaults standardUserDefaults] objectForKey:#"strains"];
if (dataSave != Nil)
{
favoritesArrayset = [NSKeyedUnarchiver unarchiveObjectWithData:dataSave];
for (NSDictionary *item in favoritesArrayset)
{
BOOL isChecked = [[item objectForKey:#"checked"] boolValue];
if (isChecked == YES )
{
[favoritesArray addObject:item];
}
}
}
[favoritesTable reloadData];
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return favoritesArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSArray *Strains = [favoritesArray copy];
NSArray *dataArray = [favoritesArray copy];
static NSString *strainTableIdentifier = #"StrainTableCell";
StrainTableCell *cell = (StrainTableCell *)[tableView dequeueReusableCellWithIdentifier:strainTableIdentifier];
if (cell == nil)
{
cell = [[StrainTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:strainTableIdentifier] ;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"StrainTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
cell.titleLabel.text = [[Strains objectAtIndex:indexPath.row] objectForKey:#"Title"];
cell.descriptionLabel.text = [[Strains objectAtIndex:indexPath.row] objectForKey:#"Description"];
cell.ratingLabel.text = [[Strains objectAtIndex:indexPath.row] objectForKey:#"Rating"];
cell.ailmentLabel.text = [[Strains objectAtIndex:indexPath.row] objectForKey:#"Ailment"];
cell.actionLabel.text = [[Strains objectAtIndex:indexPath.row] objectForKey:#"Action"];
cell.ingestLabel.text = [[Strains objectAtIndex:indexPath.row] objectForKey:#"Ingestion"];
cell.whatCellamI = [NSNumber numberWithInt:indexPath.row];
NSMutableDictionary *item = [dataArray objectAtIndex:indexPath.row];
cell.textLabel.text = [item objectForKey:#"text"];
[item setObject:cell forKey:#"StrainTableCell"];
}
BOOL checked = [[item objectForKey:#"checked"] boolValue];
UIImage *image = (checked) ? [UIImage imageNamed:#"checked.png"] : [UIImage imageNamed:#"unchecked.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
CGRect frame = CGRectMake(0.0, 0.0, image.size.width, image.size.height);
button.frame = frame;
[button setBackgroundImage:image forState:UIControlStateNormal];
[button addTarget:self action:#selector(checkButtonTapped:event:) forControlEvents:UIControlEventTouchUpInside];
button.backgroundColor = [UIColor clearColor];
cell.accessoryView = button;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
StrainDetailViewController *detailViewController = [[StrainDetailViewController alloc]
initWithNibName:#"StrainDetailViewController" bundle:nil];
detailViewController.title = [[favoritesArray objectAtIndex:indexPath.row] objectForKey:#"Title"];
detailViewController.strainDetail = [favoritesArray objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detailViewController animated:YES];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 82;
}
- (IBAction)backbuttonpressed:(id)sender
{
[self.view.window.rootViewController dismissViewControllerAnimated:YES completion:nil];
}
- (void)checkButtonTapped:(id)sender event:(id)event
{
NSLog(#"made it here and event is %#",event);
NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:self.favoritesTable];
NSIndexPath * indexPath ;
indexPath = [self.favoritesTable indexPathForRowAtPoint: currentTouchPosition];
NSLog(#"indexpath is below");
NSLog(#"%#",indexPath);
if (indexPath != Nil)
{
NSMutableDictionary *item = [favoritesArray objectAtIndex:indexPath.row];
BOOL isItChecked = [[item objectForKey:#"checked"] boolValue];
/*
if (isItChecked == NO) {
NSMutableArray *tmpArray = [[NSMutableArray alloc] init];
NSMutableArray *tmpArray2 = [[NSMutableArray alloc] initWithArray:[favoritesArray allObjects]];
NSString *text1 = [item objectForKey:#"Title"];
for (NSDictionary * object in tmpArray2) {
NSString *text2 = [object objectForKey:#"Title"];
if (![text1 isEqualToString:text2]) {
[tmpArray addObject:object];
}
}
// [favoritesArray removeAllObjects];
favoritesArray = [tmpArray copy];
}
*/
NSMutableArray *quickArray = [[NSMutableArray alloc] initWithArray:favoritesArray];
[quickArray replaceObjectAtIndex:indexPath.row withObject:item];
[item setObject:[NSNumber numberWithBool:!isItChecked] forKey:#"checked"];
favoritesArray = [quickArray copy];
// [self.favoritesArray addObject:item];
// NSLog(#"you have added %d items to favorites", self.favoritesArray.count);
[favoritesTable reloadData];
}
#end
In your .h take one NSMutableDictionary and do property to it.
In your .m synthesize it,and in viewdidLoad alloc the Dictionary.
Now put this below code in CellForRowAtIndex
if([idDictonary objectForKey:[NSString stringWithFormat:#"%d",[indexPath row]]])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
and put this below code in DidSelectRowAtIndex
UITableViewCell *thisCell = [tableView cellForRowAtIndexPath:indexPath];
if (thisCell.accessoryType == UITableViewCellAccessoryNone)
{
thisCell.accessoryType = UITableViewCellAccessoryCheckmark;
[idDictonary setValue:[dataArray objectAtIndex:indexPath.row] forKey:[NSString stringWithFormat:#"%d",[indexPath row]]];
}
else
{
if([idDictonary objectForKey:[NSString stringWithFormat:#"%d",[indexPath row]]])
{
[idDictonary removeObjectForKey:[NSString stringWithFormat:#"%d",[indexPath row]]];
thisCell.accessoryType = UITableViewCellAccessoryNone;
}
}
[myTableView reloadData];
NSLog(#"idDictonary = %#",idDictonary);
i hope this will helps u Brittany...
Every time -tableView:cellForRowAtIndexPath: runs, you create a new button, set it to the desired properties and … throw it away. (Seems to be the running joke this week.) You have to use the existing button.
Please help me I am not able to understand why this is happening there a object _getProductType is deallocate without any reason. please take a look, I am not able to figure out what is happening , if you can help me I will be very thank full to you, Thanks in advance
//
// ProductComponentViewController.m
// TurfNutritionTool
//
// Created by Aashish Joshi on 10/14/11.
// Copyright 2011 Abacus Consultancy Services. All rights reserved.
//
#import "ProductComponentViewController.h"
#import <QuartzCore/QuartzCore.h>
#implementation ProductComponentViewController
#synthesize productTableView = _productTableView;
#synthesize productTypeSelector = _productTypeSelector;
#synthesize turftypePopover = _turftypePopover;
#synthesize gotTurftype = _gotTurftype;
#synthesize resultProduct = _resultProduct;
#synthesize productTableCellStyle = _productTableCellStyle;
#synthesize dbObject = _dbObject;
#synthesize getProductType = _getProductType;
#define Granular #"G"
#define Liquid #"L"
#define Tankmix #"T"
#define AllProduct #"A"
- (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)viewDidLoad
{
[super viewDidLoad];
// D o any additional setup after loading the view from its nib.
UIColor *_background = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"main_bg.png"]];
self.view.backgroundColor = _background;
[_background release];
// init the segment button value
[productTypeSelector setSelectedSegmentIndex:0];
_getProductType = [[NSString alloc] initWithString:AllProduct];
// set table delegate
_productTableView.delegate = self;
// load the product
[self loadProductComponentValues];
// Set the table view to be rounded
[[_productTableView layer] setCornerRadius:5.0];
}
- (void)viewDidUnload
{
[self setProductTableView:nil];
[self setProductTypeSelector:nil];
_productTableView = nil;
_productTypeSelector = nil;
_turftypePopover = nil;
_gotTurftype = nil;
_resultProduct = nil;
_productTableCellStyle = nil;
_getProductType = nil;
[_getProductType release];
[_productTableView release];
[_productTypeSelector release];
[_turftypePopover release];
[_gotTurftype release];
[_resultProduct release];
[_productTableCellStyle release];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
}
- (void)dealloc {
[_getProductType release];
[_productTableView release];
[_productTypeSelector release];
[_turftypePopover release];
[_gotTurftype release];
[_resultProduct release];
[_productTableCellStyle release];
[super dealloc];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// #warning Incomplete method implementation.
// Return the number of rows in the section.
// NSLog(#"%s", __FUNCTION__);
return [self.resultProduct count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"productContentTableCellStyle" owner:self options:nil];
cell = _productTableCellStyle;
self.productTableCellStyle = nil;
}
NSDictionary * _productRow = [_dbObject getProductdetail:[self.resultProduct objectAtIndex:indexPath.row]];
// Configure the cell...
UILabel* _label = (UILabel *)[cell viewWithTag:1];
NSString* _linkcode = [_productRow objectForKey:#"linkcode"];
_label.text = _linkcode;
_label = (UILabel *)[cell viewWithTag:2];
NSString* _description = [_productRow objectForKey:#"description"];
_label.text = _description;
_label = (UILabel *)[cell viewWithTag:3];
NSString* _productcode = [_productRow objectForKey:#"productcode"];
_label.text = _productcode;
_label = (UILabel *)[cell viewWithTag:4];
NSString* _weight = [_productRow objectForKey:#"weight"];
_label.text = _weight;
_label = (UILabel *)[cell viewWithTag:6];
NSNumber* _costperBag = [[NSNumber alloc] initWithFloat:[[_dbObject getUserProductCost:[self.resultProduct objectAtIndex:indexPath.row]] floatValue]];
_label.text = [#"$ " stringByAppendingString:[_costperBag stringValue]];
[_costperBag autorelease];
_getProductType = [_productRow objectForKey:#"producttype"];
if ([_getProductType isEqualToString:#"G"]) {
_label = (UILabel *)[cell viewWithTag:10];
NSString* _weightTag = [[NSString alloc] initWithString:#"Weight in Lbs"];
_label.text = _weightTag;
[_weightTag autorelease];
_label = (UILabel *)[cell viewWithTag:11];
NSString* _SGNTag = [[NSString alloc] initWithString:#"SGN"];
_label.text = _SGNTag;
[_SGNTag autorelease];
_label = (UILabel *)[cell viewWithTag:5];
NSString* _sgn = [_productRow objectForKey:#"sgn"];
_label.text = _sgn;
} else if([_getProductType isEqualToString:#"L"]) {
_label = (UILabel *)[cell viewWithTag:10];
NSString* _weightTag = [[NSString alloc] initWithString:#"Weight in Ozs"];
_label.text = _weightTag;
[_weightTag autorelease];
_label = (UILabel *)[cell viewWithTag:11];
NSString* _SGTag = [[NSString alloc] initWithString:#"SG"];
_label.text = _SGTag;
[_SGTag autorelease];
_label = (UILabel *)[cell viewWithTag:5];
NSString* _sgn = [_productRow objectForKey:#"sg"];
_label.text = _sgn;
} else if([_getProductType isEqualToString:#"T"]) {
_label = (UILabel *)[cell viewWithTag:10];
NSString* _weightTag = [[NSString alloc] initWithString:#"Weight in Ozs"];
_label.text = _weightTag;
[_weightTag autorelease];
_label = (UILabel *)[cell viewWithTag:11];
NSString* _SGTag = [[NSString alloc] initWithString:#"SG"];
_label.text = _SGTag;
[_SGTag autorelease];
_label = (UILabel *)[cell viewWithTag:5];
NSString* _sgn = [_productRow objectForKey:#"sg "];
_label.text = _sgn;
}
return cell;
}
- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIColor *_background = [[[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"toolbar_bkg.png"]] autorelease];
UIView* _customView = [[[UIView alloc]initWithFrame:CGRectMake(10.0, 0.0, 300.0, 44.0)]autorelease];
_customView.backgroundColor = _background;
return _customView;
}
- (UIView *) tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
UIColor *_background = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"toolbar_bkg.png"]];
UIView* _customView = [[[UIView alloc]initWithFrame:CGRectMake(10.0, 0.0, 300.0, 44.0)]autorelease];
_customView.backgroundColor = _background;
[_background release];
return _customView ;
}
#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];
[detailViewController release];
if (_delegate != nil) {
NSString *_selectedTurftype = [_getTurftype objectAtIndex:indexPath.row];
[_delegate getSelectedTurftype:_selectedTurftype];
}
*/
// NSDictionary * _productRow = [_dbObject getProductdetail:[self.resultProduct objectAtIndex:indexPath.row]];
// Animate the deselection
[self.productTableView deselectRowAtIndexPath:[self.productTableView indexPathForSelectedRow] animated:YES];
CGRect _popoverRect = CGRectMake(800.0f, 380.0f, 10.0f, 10.0f);
if ([_turftypePopover isPopoverVisible]) {
[_turftypePopover dismissPopoverAnimated:YES];
}
else
{
ProductDetailViewController* _productDetailViewControllerObj = [[ProductDetailViewController alloc] init];
_turftypePopover = [[UIPopoverController alloc]
initWithContentViewController:_productDetailViewControllerObj];
_productDetailViewControllerObj.dbObject = _dbObject;
[_productDetailViewControllerObj getSelectedProductId:[self.resultProduct objectAtIndex:indexPath.row] ];
[_productDetailViewControllerObj release];
_turftypePopover.popoverContentSize = CGSizeMake(360, 500);
[_turftypePopover presentPopoverFromRect:_popoverRect inView:self.view
permittedArrowDirections:0 animated:YES];
}
[self.productTableView deselectRowAtIndexPath:[self.productTableView indexPathForSelectedRow] animated:YES];
}
#pragma mark - ProductComponentViewController lifecycle methods
- (IBAction)laodTurftype:(id)sender {
[self initAllTheProduct];
if (_getProductType == (id)[NSNull null] && _getProductType == nil) {
_getProductType = [NSString stringWithString:AllProduct];
}
if ([_turftypePopover isPopoverVisible]) {
[_turftypePopover dismissPopoverAnimated:YES];
}
else
{
TurftypePopoverViewController* _turftypeControllerObj = [[TurftypePopoverViewController alloc] init];
_turftypeControllerObj.dbObject = _dbObject;
_turftypeControllerObj.delegate = self;
_turftypePopover = [[UIPopoverController alloc]
initWithContentViewController:_turftypeControllerObj];
[_turftypeControllerObj release];
_turftypePopover.popoverContentSize = CGSizeMake(150, 225);
[_turftypePopover presentPopoverFromBarButtonItem:sender
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}
}
- (IBAction)setProductType:(id)sender {
switch (_productTypeSelector.selectedSegmentIndex) {
case 0:
_getProductType = [NSString stringWithString:AllProduct];
break;
case 1:
_getProductType = [NSString stringWithString:Granular];
break;
case 2:
_getProductType = [NSString stringWithString:Liquid];
break;
case 3:
_getProductType = [NSString stringWithString:Tankmix];
break;
}
[self loadProductComponentValues];
// Check Point
[TestFlight passCheckpoint:#"SET_PRODUCT_TYPE"];
}
// This is Delgate Method to get selceted product
-(void) getSelectedTurftype:(NSString*) getTurftype {
self.gotTurftype = getTurftype;
NSLog(#"self.gotTurftype %#", self.gotTurftype);
[self loadProductComponentValues];
if ([_turftypePopover isPopoverVisible]) {
[_turftypePopover dismissPopoverAnimated:YES];
}
}
-(void) initAllTheProduct {
_getProductType = [NSString stringWithString:AllProduct];
self.gotTurftype = nil;
// init the segment button value
[productTypeSelector setSelectedSegmentIndex:0];
[self loadProductComponentValues];
// Check Point
[TestFlight passCheckpoint:#"SET_ALL_PRODUCT"];
}
- (IBAction)setAllProduct:(id)sender {
[self initAllTheProduct];
}
// This Method use for Load Value of ProductComponent
- (NSMutableArray*) loadProductComponentValues {
[self.resultProduct removeAllObjects];
if (!_dbObject) [self loadDBAccessDatabase];
self.resultProduct = [[NSMutableArray alloc] initWithArray:[self.dbObject getRelatedProductArray:self.gotTurftype andProductType:_getProductType]];
[_productTableView reloadData];
return self.resultProduct;
}
- (NSMutableArray *) loadProductComponentValuesIfEmpty {
// NSLog(#"%s", __FUNCTION__);
[self initAllTheProduct];
if (!_dbObject) [self loadDBAccessDatabase];
if (!self.resultProduct || ![self.resultProduct count]) self.resultProduct = [[NSMutableArray alloc] initWithArray:[self.dbObject getRelatedProductArray:self.gotTurftype andProductType:_getProductType]];
// Check Point
[TestFlight passCheckpoint:#"LOAD_DATABASE"];
return self.resultProduct;
}
- (DBAccess *) loadDBAccessDatabase {
// NSLog(#"%s", __FUNCTION__);
if (!_dbObject) {
NSString * _dbFileName = #"turfnutritiontool.db";
_dbObject = [[DBAccess alloc] initWithSSDBAccessFilename:_dbFileName];
}
return _dbObject;
}
#end
Prefer using property accessors to directly accessing instance variables in methods other than init... and dealloc. For example, there are a number of places where your code is currently doing things like this:
_getProductType = [NSString stringWithString:AllProduct];
Leaving aside that getProductType is a silly name for a property (which goes double for the instance variable, not to mention that the synthesized setter method name would be setGetProductType), this code directly assigns an object to an instance variable without taking ownership of the object. Don't do this. Instead, do one of the following:
// First let's rename your property. In the .h file, modify the current declaration like so:
#property (nonatomic, copy) NSString *productType;
// In the .m file, change the #synthesize statement:
#synthesize productType = _productType;
// In cleaning up any compiler errors/warnings from references to the old names,
// modify code that directly assigns to the instance variable (other than in `dealloc`):
// So change this:
_getProductType = [NSString stringWithString:AllProduct];
// to the following:
self.productType = [NSString stringWithString:AllProduct];
// ...or better yet:
self.productType = AllProduct;
// Note that the above statement is equivalent to the following:
[self setProductType:AllProduct];
EDIT
Also as #samfisher correctly points out, don't set ivars to nil before sending them release messages in dealloc.
use:
self._getProductType = [[NSString alloc] initWithString:AllProduct];
change this sequence:
[_getProductType release];
[_productTableView release];
[_productTypeSelector release];
[_turftypePopover release];
[_gotTurftype release];
[_resultProduct release];
[_productTableCellStyle release];
_productTableView = nil;
_productTypeSelector = nil;
_turftypePopover = nil;
_gotTurftype = nil;
_resultProduct = nil;
_productTableCellStyle = nil;
_getProductType = nil;
you were leaking memory as setting pointers to nil, //memory leak
first you should release then set pointers to nil;// no leak
When _getProductType is allocated on this line
_getProductType = [[NSString alloc] initWithString:AllProduct];
it is not retained in any way.
and as soon as _getProductType goes out of scope (which is after viewDidLoad finishes) you will not be able to reference a valid object.
so every time you reference _getProductType outside of viewDidLoad it will be as if 'released'.
Your dealloc method releases it correctly so all you have to do is add a 'retain' after allocation/initialisation, thus:
_getProductType = [[[NSString alloc] initWithString:AllProduct] retain];
However, it might be a really good idea to study properties and how they work, how they can be set up to do things like retaining or copying data as and when it is initialised. Your starting point is here.
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;
}