objectForKey returns nil on a dictionary - objective-c

I am creating a recipe manager app for iPad. I am using the split view template which loads data for the recipes from a plist which is structured in this way. The table view on the left works perfectly. It loads the data from the plist. The problem is the detail view. As you can see I have inserted a NSLog lines in the DetailViewController.m file since every string I passed to the text field resulted as nil. Strangely, when I tried to NSLog from the RootViewController.m with:
NSLog(#"%#", [detailViewController.ricetta allKeys])
it worked.
Any suggestions?
I tried to post as much lines as possible to explain the problem as well as possible.
<plist version="1.0">
<array>
<dict>
<key>name</key>
<string>Risotto alla zucca</string>
<key>ingredients</key>
<string></string>
<key>description</key>
<string></string>
<key>photo</key>
<string></string>
</dict>
<dict>
<key>name</key>
<string>Semi di zucca al forno</string>
<key>ingredients</key>
<string></string>
<key>description</key>
<string></string>
<key>photo</key>
<string></string>
</dict>
<dict>
<key>name</key>
<string>Risotto ai funghi</string>
<key>ingredients</key>
<string></string>
<key>description</key>
<string></string>
<key>photo</key>
<string></string>
</dict>
</array>
</plist>
RootViewController.h
#import <UIKit/UIKit.h>
#import "RecipeConstants.h"
#class DetailViewController;
#interface RootViewController : UITableViewController {
NSMutableArray *ricette;
}
#property (nonatomic, retain) NSMutableArray *ricette;
#property (nonatomic, retain) IBOutlet DetailViewController *detailViewController;
#end
RootViewController.m
...
#synthesize ricette;
- (void)viewDidLoad
{
[super viewDidLoad];
self.clearsSelectionOnViewWillAppear = NO;
self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0);
NSString *path = [[NSBundle mainBundle] pathForResource:#"RicetteArray" ofType:#"plist"];
NSMutableArray *tmpArray = [[NSMutableArray alloc] initWithContentsOfFile:path];
self.ricette = tmpArray;
[tmpArray release];
}
...
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.ricette count];
}
// Configure the cell.
cell.textLabel.text = [[self.ricette objectAtIndex:indexPath.row] objectForKey:NAME_KEY];
return cell;
}
...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
detailViewController.ricetta = [self.ricette objectAtIndex:indexPath.row];
}
...
- (void)dealloc
{
[detailViewController release];
[ricette release];
[super dealloc];
}
#end
DetailViewController.h
#import <UIKit/UIKit.h>
#import "RecipeConstants.h"
#interface DetailViewController : UIViewController <UIPopoverControllerDelegate, UISplitViewControllerDelegate> {
IBOutlet UILabel *lblTitolo;
IBOutlet UITextView *ingredientiTxtView;
IBOutlet UITextView *descrizioneTxtView;
IBOutlet UIImageView *fotoImgView;
NSDictionary *ricetta;
}
#property (nonatomic, retain) IBOutlet UILabel *lblTitolo;
#property (nonatomic, retain) IBOutlet UITextView *ingredientiTxtView;
#property (nonatomic, retain) IBOutlet UITextView *descrizioneTxtView;
#property (nonatomic, retain) IBOutlet UIImageView *fotoImgView;
#property (nonatomic, retain) NSDictionary *ricetta;
#property (nonatomic, retain) IBOutlet UIToolbar *toolbar;
#property (nonatomic, retain) id detailItem;
#end
DetailViewController.m
#synthesize lblTitolo, ingredientiTxtView, descrizioneTxtView, fotoImgView, ricetta;
...
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
lblTitolo.text = [ricetta objectForKey:NAME_KEY];
ingredientiTxtView.text = [ricetta objectForKey:INGREDIENTS_KEY];
descrizioneTxtView.text = [ricetta objectForKey:DESCRIPTION_KEY];
UIImage *img = [UIImage imageNamed:PHOTO_KEY];
fotoImgView.image = img;
NSLog(#"%#", [ricetta allKeys]);
}
...
- (void)dealloc
{
[_myPopoverController release];
[_toolbar release];
[_detailItem release];
[lblTitolo release];
[ingredientiTxtView release];
[descrizioneTxtView release];
[fotoImgView release];
[ricetta release];
[super dealloc];
}
#end
UPDATE:
Actually in the DetailViewController.m I have this method:
- (void)updateRicetta {
lblTitolo.text = [ricetta objectForKey:NAME_KEY];
NSString *myIngredients = [ricetta objectForKey:INGREDIENTS_KEY];
myIngredients = [myIngredients stringByReplacingOccurrencesOfString:#", " withString:#"\n"];
ingredientiTxtView.text = myIngredients;
NSString *myDescription = [ricetta objectForKey:DESCRIPTION_KEY];
myDescription = [myDescription stringByReplacingOccurrencesOfString:#". " withString:#"\n"];
descrizioneTxtView.text = myDescription;
NSString *nomeImmagine = [NSString stringWithFormat:#"%#.jpg", [ricetta objectForKey:PHOTO_KEY]];
[self.fotoImgView setImage:[UIImage imageNamed:nomeImmagine]];
}
which is called from RootViewController.m in
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
using
[detailViewController updateRicetta];
I have the following two warnings:
'DetailViewController' may not respond to '-updateRicetta'
Instance method '-updateRicetta not found (return type defaults to 'id')
Another problem is that the detail view updates only when I click on a cell not at app loading.

I'm happy to be wrong about this, but it looks to me like when you call tableView:didSelectRowAtIndexPath: you set the recipe (ricetta?) in the DetailViewController but I don't see any instruction to tell the DetailViewController to display the new recipe.
You have code to update your DetailViewController in viewWillAppear:animated: but this will only happen when the view is going to appear - if your view has already appeared this method won't be executed.
I suggest you create a method in DetailViewController called updateRicetta which will look something like:
- (void)updateRicetta {
lblTitolo.text = [ricetta objectForKey:NAME_KEY];
ingredientiTxtView.text = [ricetta objectForKey:INGREDIENTS_KEY];
descrizioneTxtView.text = [ricetta objectForKey:DESCRIPTION_KEY];
UIImage *img = [UIImage imageNamed:PHOTO_KEY];
fotoImgView.image = img;
}
You could then call this from tableView:didSelectRowAtIndexPath: -
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
detailViewController.ricetta = [self.ricette objectAtIndex:indexPath.row];
[detailViewController updateRicetta];
}
As to the returning nil: my guess is that when viewWillAppear:animated: is called you have not yet selected an entry and therefore ricetta has not yet been set in the DetailViewController.

Related

Unknown Type Name 'studentController'

I am making a table view application and it will not recognize the type studentController in the studentAddController.h. I have a previous project that I looked at and cannot figure out why it can not recognize the type name.
Here is the code in the studentController.h
#import <UIKit/UIKit.h>
#import "studentCells.h"
#import "AssignmentsController.h"
#import "studentAddController.h"
#interface studentController : UITableViewController {
NSMutableArray *studentArray;
}
- (IBAction)addStudentButton:(id)sender;
- (void)insertNewRow:(NSDictionary *)studentDictionary;
#property (nonatomic, retain) UITableView *studentTableView;
#end
Here is the code in the studentController.m
#import "studentController.h"
#implementation studentController
-(id)initWithStyle:(UITableViewStyle)style {
self =[super initWithStyle:style];
if (self) {
}
return self;
}
-(void)viewDidLoad {
[super viewDidLoad];
studentArray = [[NSMutableArray alloc] initWithObjects: nil];
}
- (IBAction)addStudentButton:(id)sender {
studentAddController *studentAddView =[self.storyboard instantiateViewControllerWithIdentifier:#"studentAddView"];
[self.navigationController pushViewController:studentAddView animated:YES];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [studentArray count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *studentCellIdentifier = #"studentCell";
studentCells *cell = [tableView dequeueReusableCellWithIdentifier:studentCellIdentifier forIndexPath:indexPath];
NSDictionary *studentDictionary = [studentArray objectAtIndex:[indexPath row]];
[cell.firstNameCellLabel setText:[studentDictionary objectForKey:#"First Name"]];
[cell.lastNameCellLabel setText:[studentDictionary objectForKey:#"Last Name"]];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
AssignmentsController *assignmentView = [self.storyboard instantiateViewControllerWithIdentifier:#"assignmentView"];
[self.navigationController pushViewController:assignmentView animated:YES];
}
-(void)insertNewRow:(NSDictionary *)studentDictionary {
[studentArray addObject:studentDictionary];
[self.tableView beginUpdates];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[studentArray count] -1 inSection:0];
[self.tableView insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
[self.tableView endUpdates];
}
#end
Here is the code for studentAddController.h
#import <UIKit/UIKit.h>
#import "studentController.h"
#import "studentAddController.h"
#interface studentAddController : UIViewController
#property (weak, nonatomic) IBOutlet UITextField *firstNameField;
#property (weak, nonatomic) IBOutlet UITextField *lastNameField;
- (IBAction)doneButton:(id)sender;
- (IBAction)keyboardResign:(id)sender;
#property (nonatomic, strong) studentController *parentTableVC;
#end
Here is the code in the studentAddController.m
#import "studentAddController.h"
#implementation studentAddController
- (IBAction)doneButton:(id)sender {
NSDictionary *studentDictionary =#{ #"First Name" : [self.firstNameField text],
#"Last Name" : [self.lastNameField text]
};
[self.parentTableVC insertNewRow:studentDictionary];
[self.navigationController popViewControllerAnimated:YES];
}
- (IBAction)keyboardResign:(id)sender {
[self resignFirstResponder];
}
#end
You have a circular reference. In studentController.h you import studentAddController.h and in studentAddController.h you import studentController.h. Try making these changes to your headers:
studentController.h
#import <UIKit/UIKit.h>
#import "studentCells.h"
#import "AssignmentsController.h"
studentController.m
#import "studentController.h"
#import "studentAddController.h"
studentAddController.h
#import <UIKit/UIKit.h>
#import "studentController.h"
I would also note that naming standards would dictate your classes are PascalCase not camelCase. Only your variables and methods should be camelCase.
I would also note that you didn't need to import studentAddController in studentController.h so I just moved it to the .m. If you actually needed to import studentAddController then you would do a forward class declaration to avoid a circular reference. Like this:
#import <UIKit/UIKit.h>
#import "studentCells.h"
#import "AssignmentsController.h"
#class studentAddController;

UITableView push to My webView

I'd like to start by apologising as I'm sure this question has been answered, in various forms on this site and others, but I just can't seem to implement any similar threads
It's just I have been trying to push a array of search engines into my webView,
I have populated the table with a .plist or NSMutableArray and I have an array of both kinds with Url's in I have manages to load a subview but I an really struggling to get my web view loading.
I think I'm ok until didSelectRowAtIndexPath and the webView load request. Ok thinking about it I have only populated the table and put IBOUTLET (nonatomic, retain) UIWebView *webView and synthesised it in my WebViewController.
And as Background my TableViewController is embedded in a NavigationController and a WebView in a UIViewController
If anyone is willing to help me out I'm more than willing to donate as this has caused way too many sleepless nights.
Here is a link to my project if it would help anyone http://dl.dropbox.com/u/28335617/TableViewArrays.zip
Thank you very much for any help offered
Here is my TableViewController.h
#class WebViewController;
#import <UIKit/UIKit.h>
#interface TableViewController : UITableViewController <UITableViewDataSource, UITableViewDelegate> {
WebViewController *viewController;
IBOutlet UITableView *mytableView;
}
#property (strong, nonatomic) IBOutlet UITableView *mytableView;
#property (nonatomic, retain) WebViewController *viewController;
#property (nonatomic, retain) NSMutableArray *searchData, *tableData, *tableUrl;
#end
Here is my TableViewController.m
#import "TableViewController.h"
#import "TableAppDelegate.h"
#import "WebViewController.h"
#interface TableViewController ()
#end
#implementation TableViewController
#synthesize mytableView;
#synthesize viewController;
#synthesize searchData, tableData, tableUrl;
NSMutableArray *searchData, *tableData, *tableUrl;
- (void)viewDidLoad
{
[super viewDidLoad];
tableUrl = [[NSMutableArray alloc] init];
[tableUrl addObject: #"http://www.google.com"];
[tableUrl addObject: #"http://www.bing.com"];
[tableUrl addObject: #"http://www.dogpile.com"];
[tableUrl addObject: #"http://www.wikipedia.com"];
[tableUrl addObject: #"http://www.ask.com"];
[tableUrl addObject: #"http://www.yahoo.com"];
[tableUrl addObject: #"http://www.aol.com"];
[tableUrl addObject: #"http://www.altavista.com"];
[tableUrl addObject: #"http://www.gigablast.com"];
[tableUrl addObject: #"http://www.msn.com"];
[tableUrl addObject: #"http://www.mamma.com"];
self.title = #"Search Engines";
//ARRAY FOR PLIST
// Find out the path of recipes.plist
NSString *path = [[NSBundle mainBundle] pathForResource:#"searchData" ofType:#"plist"];
searchData = [[NSMutableArray alloc] initWithContentsOfFile:path];
// Load the file content and read the data into arrays
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
tableData = [dict objectForKey:#"SearchEngines"];
// tableUrl = [dict objectForKey:#"SearchAddress"];
// NSString *path = [[NSBundle mainBundle] pathForResource:#"sEArray" ofType:#"plist"];
// sEArray = [[NSMutableArray alloc] initWithContentsOfFile:path];
// NSString *urlArray = [[NSBundle mainBundle] pathForResource:#"urlsArray" ofType:#"plist"];
//urlsArray = [[NSMutableArray alloc] initWithContentsOfFile:urlArray];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section
{
// Return the number of rows in the section.
return [self.tableData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
}
// Configure the cell...
NSInteger row = [indexPath row];
cell.textLabel.text = [tableData objectAtIndex:row];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
#pragma mark - Table view delegate
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
}
#end
And here is my WebViewController.h
#import <UIKit/UIKit.h>
#interface WebViewController : UIViewController {
NSMutableArray *tableURL;
}
#property (nonatomic, retain) IBOutlet UIWebView *webView;
#property (nonatomic, retain) NSMutableArray *tableUrl;
#end
And WebViewController.m
#import "TableAppDelegate.h"
#import "TableViewController.h"
#import "WebViewController.h"
#interface WebViewController ()
#end
#implementation WebViewController
#synthesize tableUrl;
#synthesize webView;
Not tested. Add SequgeIdentifier "WebView" in IB
in tableviewcontroller add:
- (void)viewDidLoad
{
...
tableUrl = [dict objectForKey:#"SearchAddress"];
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:#"WebView" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"WebView"])
{
WebViewController *webViewController = segue.destinationViewController;
NSIndexPath *selectedPath = [self.tableView indexPathForSelectedRow];
webViewController.tableUrl = [tableUrl objectAtIndex:[selectedPath row]];
[self.tableView deselectRowAtIndexPath:selectedPath animated:YES];
}
}
in webviewcontroller
#interface WebViewController : UIViewController {
NSString *tableURL;
}
#property (nonatomic, retain) IBOutlet UIWebView *webView;
#property (nonatomic, retain) NSString *tableUrl;
#end
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//Create a URL object.
NSURL *url = [NSURL URLWithString:tableUrl];
//URL Requst Object
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
//Load the request in the UIWebView.
[webView loadRequest:requestObj];
}
What exactly is not working?
Looking at your code, I immediately see that you cell initiation code is empty
if (cell == nil) {
}
I think you should initiate your cell with something like this:
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

IOS loading a tableview with data

I'm fairly new to iOS and have much more to learn, and hope you guys can guide me from my mistake.
I've recently learned passing data from TableView to DetailView, and thought, why not the other way around. I also start building a StopWatch app, and felt that a log function would be very useful.
With that said, I'm currently building a stopwatch app that works as a timer and have a high score log function. It goes from View(stopwatch) to tableView(log board) I'm using a NSMutableArray as a temp storage to hold the information as they should be lost when the app start/close. Unfortunately, it seem that by following and changing variable here and there, i got myself confuse and stuck now.
Thanks for the suggestion and help you guys gave and thanks #Abizern for giving me tips. Manage to solve all the problem. Shall leave the code here incase anyone in the future do similar things to this.
TimerViewController.h
#import <UIKit/UIKit.h>
#import "SampleData.h"
#import "SampleDataDAO.h"
#import "HighScoreTableViewController.h"
#interface TimerViewController : UIViewController
{
NSTimer *stopWatchTimer; // Store the timer that fires after a certain time
NSDate *startDate; // Stores the date of the click on the start button
}
#property(nonatomic, strong) SampleDataDAO *daoDS;
#property(nonatomic, strong) NSMutableArray *ds;
#property (retain, nonatomic) IBOutlet UILabel *stopWatchLabel;
#property (weak, nonatomic) IBOutlet UIButton *onStartPressed;
#property (weak, nonatomic) IBOutlet UIButton *onStopPressed;
#property (weak, nonatomic) IBOutlet UIButton *onLogPressed;
#property (weak, nonatomic) IBOutlet UIButton *onHighscorePressed;
- (IBAction)onStartPressed:(id)sender;
- (IBAction)onStopPressed:(id)sender;
- (IBAction)onLogPressed:(id)sender;
- (IBAction)onHighscorePressed:(id)sender;
#end
TimerViewController.m
#import "TimerViewController.h"
#interface TimerViewController ()
#end
#implementation TimerViewController
#synthesize stopWatchLabel;
#synthesize onStartPressed;
#synthesize onStopPressed;
#synthesize onLogPressed;
#synthesize onHighscorePressed;
#synthesize ds,daoDS;
- (void)viewDidLoad
{
[super viewDidLoad];
daoDS = [[SampleDataDAO alloc] init];
self.ds = daoDS.PopulateDataSource;
onStopPressed.enabled=false;
}
- (void)viewDidUnload
{
[self setStopWatchLabel:nil];
[self setOnStartPressed:nil];
[self setOnLogPressed:nil];
[self setOnStopPressed:nil];
[self setOnHighscorePressed:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"showDetail"]) {
HighScoreTableViewController *detailViewController = [segue destinationViewController];
detailViewController.arrayOfSampleData = self.ds;
}
}
- (void)updateTimer
{
NSDate *currentDate = [NSDate date];
NSTimeInterval timeInterval = [currentDate timeIntervalSinceDate:startDate];
NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"HH:mm:ss.S"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
NSString *timeString=[dateFormatter stringFromDate:timerDate];
stopWatchLabel.text = timeString;
}
- (IBAction)onStartPressed:(id)sender {
startDate = [NSDate date];
// Create the stop watch timer that fires every 10 ms
stopWatchTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/10.0
target:self
selector:#selector(updateTimer)
userInfo:nil
repeats:YES];
onStartPressed.enabled=false;
onStopPressed.enabled=true;
}
- (IBAction)onStopPressed:(id)sender {
[stopWatchTimer invalidate];
stopWatchTimer = nil;
[self updateTimer];
onStartPressed.enabled=true;
}
- (IBAction)onLogPressed:(id)sender {
NSString * timeCaptured = stopWatchLabel.text;
static NSInteger i = 1 ;
SampleData* mydata = [[SampleData alloc]init];
mydata.clueName=[NSString stringWithFormat:#"clue %d",i++ ];
mydata.timeLog = timeCaptured;
[self.ds addObject:mydata];
NSLog(#"%#",mydata.clueName);
NSLog(#"time %#", mydata.timeLog);
NSLog(#"%d",[self.ds count]);
mydata=nil;
}
- (IBAction)onHighscorePressed:(id)sender {
NSLog(#"Proceeding to HighScore");
}
#end
HighScoreTableView.h
#import <UIKit/UIKit.h>
#import "SampleData.h"
#import "SampleDataDAO.h"
#import "TimerViewController.h"
#interface HighScoreTableViewController : UITableViewController
#property (nonatomic, strong) NSMutableArray *arrayOfSampleData;
#property (nonatomic, strong) SampleData * highscoreData;
#end
HighScoreTableView.m
#import "HighScoreTableViewController.h"
#interface HighScoreTableViewController ()
#end
#implementation HighScoreTableViewController
#synthesize highscoreData;
#synthesize arrayOfSampleData;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
highscoreData = [[SampleData alloc]init];
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.arrayOfSampleData.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"highscoreCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
//highscoreData = [self.arrayOfSampleData objectAtIndex:indexPath.row];
highscoreData = (SampleData *)[self.arrayOfSampleData objectAtIndex:indexPath.row]; //if above line doesn't work, use this
cell.textLabel.text=[NSString stringWithFormat:#"%# time %#",highscoreData.clueName, highscoreData.timeLog];
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
*/
}
#end
SampleData.h
#import <Foundation/Foundation.h>
#interface SampleData : NSObject
#property(nonatomic,strong) NSString * clueName;
#property(nonatomic,strong) NSString * timeLog;
#end
SampleData.m
#import "SampleData.h"
#implementation SampleData
#synthesize clueName,timeLog;
#end
SampleDataDAO.h
#import <Foundation/Foundation.h>
#import "SampleData.h"
#interface SampleDataDAO : NSObject
#property(nonatomic, strong) NSMutableArray * someDataArray;
-(NSMutableArray *)PopulateDataSource;
#end
SampleDataDAO.m (Not sure if this DAO NSObject is needed)
#import "SampleDataDAO.h"
#implementation SampleDataDAO
#synthesize someDataArray;
-(NSMutableArray *)PopulateDataSource
{
someDataArray = [[NSMutableArray alloc] init];
SampleData * mydata = [[SampleData alloc] init];
mydata = nil;
return someDataArray;
}
#end
There are several missteps in your coding:
You do need to use prepareForSegue to pass data from parent to child view controller. In your case from TimerViewController to HighScoreTableViewController.
In your HighScoreTableViewController class, create an iVar array that will hold the array of sampleData that you will pass over from TimerViewController instant via the prepareForSeque. Something like this:
HighScoreTableViewController.h
#property (nonatomic, strong) NSArray *arrayOfSampleData;
3 . In your prepareForSeque of the TimerViewController, this line is wrong:
//TimerViewController.highscoreData = [self.ds objectAtIndex:[self.tableView indexPathForSelectedRow].row];
Try this:
detailViewController.arrayOfSampleData = self.ds;
4 . In the HighScoreTableViewController.m, under viewDidLoad, replace this
highscoreData = (SampleData *)self.highscoreData;
with:
highscoreData = [SampleData alloc]init];
5 . In numberOfRowsInSection, you now can do this:
return self.arrayOfSampleData.count;
6 . In the cellForRowAtIndexPath,
highscoreData = [self.arrayOfSampleData objectAtIndex:indexPath.row];
//highscoreData = (SampleData *)[self.arrayOfSampleData objectAtIndex:indexPath.row]; //if above line doesn't work, use this
cell.textLabel.text = #"%# time %# ", highscoreData.clueName, highscoreData.timeLog;
In your HighScoreTableViewController you need access to your array e.g. by declaring and defining a writable property:
#property(nonatomic, strong) NSMutableArray *myArr;
then you can define
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.myArr count];
}
and
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// ... like in your code
// Tried changing variable here and there base on tutorial, but can't seem to get it right.**
SampleData * sample = (SampelData *) [self.myArr objectAtIndex:indexPath.row];
cell.textLabel.text = #"%# time %# ",sample.clueName, sample.timeLog;
NSLog(#"Cell Value %d %#",indexPath.row, cell.textLabel.text);
return cell;
}
So basically you just have to change two lines in the definitions of your methods. Most of the time you work with TableViews it is like this: assign the array you want to read data from to a custom property. Return the size of the array in tableView:numberOfRowsInSection: and take an object from the appropiate index to populate a cell in tableView:cellForRowAtIndexPath:.
If the contents of your array changes you have to do extra action to update your table view.
First declare the array in .h file(ex. NSMutableArray *arrStopwatchDetails).
Create the property of that array like #property(nonatomic,retain)NSMutableArray *arrStopwatchDetails.
Synthesize the array in .m file like #synthesize arrStopwatchDetails.
Allocate the array in viewDidLoad or before you want to used.
ex. self.arrStopwatchDetails = [[NSMutableArray alloc]init];
In numberOfRowsInSection method, return the count of array similar to return [self.arrStopwatchDetails count].
In cellForRowsAtIndexPath method, assign value of array element to the cell text as
SampleData * sample = [[[SampleDataDAO alloc]init ].self.arrStopwatchDetails objectAtIndex:indexPath.row];
cell.textLabel.text = #"%# time %# ",sample.clueName, sample.timeLog;
Thats it.

Passing data back :Delegate method not called

I am working on an app that connects with google docs using oauth 2.0, once the user has connected, He clicks a button that goes to a tableView to show all the documents. For this I am using a segue and passing data forward. Now I want the user to select one document, put a checkmark on it and return to the viewcontroller passing data back and display wich document was selected. I read that for passing data back I needed to use a protocol and a delegate. I followed this: Passing Data between View Controllers but my problem is that my delegate method is not being called.
Here is my storyboard, just 2 views, a viewcontroller and a tablaviewvcontroller called VistaTableViewController.
When the user pushes the authenticate button, He connects with google docs using oauth. When he pushes the "Listar" button the VistaTableViewController appears.
Here is the code of VistaTableViewController.h where a define the protocol:
#import <UIKit/UIKit.h>
#import "GData.h"
#class VistaTableViewController;
#protocol VistaTableViewControllerDelegate <NSObject>
- (void)loqueselecciono:(VistaTableViewController *)controller didSelectDoc:(NSString *)documento;
#end
#interface VistaTableViewController : UITableViewController <UITableViewDataSource>
{
IBOutlet UITableView *tablalistar;
GDataFeedDocList *mDocListFeed2;
}
#property (nonatomic, weak) id <VistaTableViewControllerDelegate> delegate;
#property (nonatomic, strong) NSString *documento;
#property (nonatomic, retain) GDataFeedDocList *mDocListFeed2;
#end
Here is the code of VistaTableViewController.m where I call the delegate method:
#import "VistaTableViewController.h"
#implementation VistaTableViewController
{
NSInteger selectedIndex;
}
#synthesize delegate;
#synthesize documento;
#synthesize mDocListFeed2;
- (void)viewDidLoad
{
[super viewDidLoad];
selectedIndex = [[mDocListFeed2 entries] indexOfObject:self.documento];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[mDocListFeed2 entries] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"tablalistar"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"tablalistar"];
}
GDataEntrySpreadsheet *doc = [[mDocListFeed2 entries] objectAtIndex:indexPath.row];
cell.textLabel.text = [[doc title] stringValue];
if (indexPath.row == selectedIndex)
cell.accessoryType = UITableViewCellAccessoryCheckmark;
else
cell.accessoryType = UITableViewCellAccessoryNone;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if (selectedIndex != NSNotFound)
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:selectedIndex inSection:0]];
cell.accessoryType = UITableViewCellAccessoryNone;
}
selectedIndex = indexPath.row;
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
GDataEntrySpreadsheet *doc = [[mDocListFeed2 entries] objectAtIndex:indexPath.row];
NSString *theDoc = [[doc title] stringValue];
[self.delegate loqueselecciono:self didSelectDoc:theDoc];
}
#end
Ok, so now I just need to tell ViewController to import VistaTableViewController and conform to its protocol.
here is the code of ViewController.h
#import <UIKit/UIKit.h>
#import "GTMOAuth2ViewControllerTouch.h"
#import "GData.h"
#import "VistaTableViewController.h"
#interface ViewController : UIViewController <VistaTableViewControllerDelegate>
- (GDataServiceGoogleDocs *)docsService;
- (void)authorize;
- (void) mifetch;
- (IBAction)autenticarse;
- (IBAction)listar:(id)sender;
- (void) ticket: (GDataServiceTicket *) ticket finishedWithFeed: (GDataFeedDocList *) feed error: (NSError *) error;
#property (nonatomic, retain) NSString *accessToken;
#property (nonatomic, retain) GDataFeedDocList *mDocListFeed;
#property (nonatomic, retain) GDataServiceTicket *mDoclistFetchTicket;
#end
Then in Viewcontroller.m I implement the delegate method as follows: (I just want to display an alert showing the title of de document that was selected).
- (void)loqueselecciono:(VistaTableViewController *)controller didSelectDoc:(NSString *)documento;
{
[self.navigationController popViewControllerAnimated:YES];
UIAlertView *alertView = [ [UIAlertView alloc] initWithTitle:#"doc seleccionado"
message:[NSString stringWithFormat:#"titulo: %#", documento]
delegate:self
cancelButtonTitle:#"Dismiss"
otherButtonTitles:nil];
[alertView show];
}
and in Viewcontroller.m as well I wrote this to assign self to the delegate.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"displaydocs"])
{
VistaTableViewController *vistatableview = [[VistaTableViewController alloc] init];
vistatableview.delegate = self;
vistatableview = [segue.destinationViewController performSelector:#selector(setMDocListFeed2:) withObject:mDocListFeed];
}
}
Ok, so I get de tableView displaying all the documents and the user can select one showing de checkmark but the delegate method is not being called so It does not return to the viewcontroller view and no data is passed back.
What am I missing?? Thanks!!
When you write VistaTableViewController *vistatableview = [[VistaTableViewController alloc] init]; you are creating a new object. What you really want to do is use the segue.destinationViewController, which should be a VistaTableViewController and set its delegate to self.
As is, the object with the delegate is not the object being pushed and handling the view logic.
(Also, setMDocListFeed2 doesn't return an object so the assignment on performSelector is rather misleading.)

Table View Controller and TextField Inside ModalView

I try to add tableView and TextField inside the ModalView. I do so. I create new View Controller and give for it
#import <UIKit/UIKit.h>
#protocol UYLModalViewControllerDelegate
-(void) buttonDonePassed :(NSArray *) variables;
#end
#interface UYLModalViewController : UIViewController <UITableViewDelegate>
{
id<UYLModalViewControllerDelegate> delegate;
IBOutlet UITableView *tblView;
IBOutlet UITextField *textField;
NSMutableArray *cellsArray;
//UITextField *textField;
}
#property (nonatomic, assign) id<UYLModalViewControllerDelegate> delegate;
#property (nonatomic, retain) IBOutlet UITableView *tblView;
#property (retain, nonatomic) IBOutlet UITextField *textField;
#end
And IN .m File I create functions
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [cellsArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = [cellsArray objectAtIndex:indexPath.row];
// Configure the cell.
return cell;
}
and ViewDidiLoad
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(buttonPassed:)];
//UITableView *tableView = [[UITableView alloc] init];
//[self]
cellsArray = [[NSMutableArray alloc] initWithObjects:#"one",#"two",#"three", nil];
[tblView reloadData];
}
But my program don't go to the TableViewDelegate methods (such as cellforrowAtIndexPath)
You need to set your UYLModalViewController as the tableView's delegate and datasource.
It looks like you are using Interface Builder so you need to:
control + click on the tableView and drag it across to the File's Owner
Then select datasource from the HUD menu.
Then repeat the process but selecting delegate
Note
Your controller should also conform to UITableViewDatasource giving you:
#interface UYLModalViewController : UIViewController <UITableViewDelegate, UITableViewDatasource>
1.
2.
If you prefer you can do this in code in viewDidLoad or any place where you create the tableView if you do it programatically.
self.tableView.delegate = self;
self.tableView.datasource = self;