I'm noob in Obj-c programming. I'm making an iPad application composed of a ViewController that shows me 2 text boxes , a button in the upper side , just to make a sum.
In the same Viewcontroller, i have a TableView and a Button. This Tableview initially shows me an element, but i'd want to refresh this list just clicking the button.
The function linked at the button to refresh the list ( touch down event ) is called " listaPDF " .
Viewcontroller.h
#import <UIKit/UIKit.h>
#interface VPViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
IBOutlet UITextField *txtPrimoAddendo ;
IBOutlet UITextField *txtSecondoAddendo ;
IBOutlet UILabel *lblTotale ;
IBOutlet UITableView *tabella;
NSMutableArray *lista;
}
#property (nonatomic, retain) IBOutlet UITextField *txtPrimoAddendo;
#property (nonatomic, retain) IBOutlet UITextField *txtSecondoAddendo;
#property (nonatomic, retain) IBOutlet UILabel *lblTotale;
#property (nonatomic, retain) IBOutlet UITableView *tabella;
#property (nonatomic, retain) NSMutableArray *lista;
-(IBAction)somma ;
-(IBAction)listaPDF;
#end
Viewcontroller.m
#import "VPViewController.h"
#interface VPViewController ()
#end
#implementation VPViewController
-(void)somma {
int x = [[txtPrimoAddendo text] intValue];
int y = [[txtSecondoAddendo text] intValue];
int somma = x + y ;
NSString *totale = [NSString stringWithFormat:#"La somma fa : %d", somma];
[lblTotale setText:totale];
[lblTotale setHidden:FALSE];
}
- (void)listaPDF {
int contatore = 1;
NSArray *dirFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[[NSBundle mainBundle] resourcePath] error: nil];
for (int i = 0; i < dirFiles.count ; i++) {
NSString *files = dirFiles[i];
int indice = files.length - 4 ;
NSString *extension = [files substringFromIndex:indice];
if([extension isEqual: #".pdf"]) {
NSLog(#"********* File PDF : %#", files);
[lista insertObject:files atIndex:contatore];
contatore++;
}
}
[tabella reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [lista count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"CellID";
UITableViewCell *cell = [tabella dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.imageView.image = [UIImage imageNamed:#"pdf.png"];
cell.textLabel.text = [lista objectAtIndex:indexPath.row];
return cell;
}
- (void)viewDidLoad
{
tabella.delegate = self;
tabella.dataSource = self;
tabella = [[ UITableView alloc] init];
lista = [[NSMutableArray alloc] init];
[lista insertObject:#"FIRST ELEMENT" atIndex:0];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
#synthesize lblTotale;
#synthesize txtPrimoAddendo;
#synthesize txtSecondoAddendo;
#synthesize tabella;
#synthesize lista;
#end
Thanks
I have tried your code as it is.
Why you initializing UITableView object in viewDidLoad. It doesn't need to be allocated if you are adding on Xib file. If you creating UITableView Programmatically then its required. Just comment/remove that initializing line and tableView's delegate methods will be called.
And In 'ListaPDF' function no items is being added to array 'lista', that's why no new entry was visible in UITableView.
NSMutableArray indices begin at 0 - not 1
int contatore = 1;
...
[lista insertObject:files atIndex:contatore];
contatore++;
Use addObject to add an object to a NSMutableArray
[lista addObject:files];
Remove all of your instance variables, because this:
#property (nonatomic, retain) NSMutableArray *lista;
creates an instance variable called _lista - not lista
You have quite a bit of code backwards:
tabella.delegate = self;
tabella.dataSource = self;
tabella = [[ UITableView alloc] init];
lista = [[NSMutableArray alloc] init];
You're trying to set the delegate and datasource before the table is allocated.
It should be:
tabella = [[ UITableView alloc] init];
lista = [[NSMutableArray alloc] init];
tabella.delegate = self;
tabella.dataSource = self;
However the UITableView has been added inside Interface Builder, right?
That means it's already being created for you and you shouldn't be allocating the table here.
Also: inside Interface Builder you can rightclick+drag (or ctrl+leftclick+drag) to connect your UITableView to yourUIViewController as its delegate and datasource
Related
While looping the
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {}
method im setting data to my custom cell (an image and a text). I was wondering what's the best way to achieve this.
I can use 2 different array (image array and text array) and do something like:
cell.image setImage: //get image from imageArray with indexPath.row
cell.text.text = [textArray objectAtIndex:indexPath.row];
or use a multi dimensional array like this:
cell.image setImage: [imageArray objectAtIndex:indexPath.row] objectAtIndex:0;
cell.text.text = [textArray objectAtIndex:indexPath.row] objectAtIndex:1;
// or use of dictionary with keys
What method is quicker or more readable?
Personally I think the following is the cleanest solution:
Create a model for the items in your array.
Create an UITableViewCell subclass to display the model in the cell. The subclass will have a property that accepts the model and redraw itself when the model changes.
Let's say we have a news app. The array is filled with items for which we create the model NewsItem. The model header could look like this:
NewsItem.h
#interface FSNewsItem : NSObject <NSCoding>
#property (nonatomic, copy, readonly) NSString *title;
#property (nonatomic, copy, readonly) NSURL *URL;
#property (nonatomic, copy, readonly) NSString *time;
#property (nonatomic, copy, readonly) NSString *points;
#property (nonatomic, copy, readonly) NSString *author;
// initialiser
+ (FSNewsItem *)newsItemWithTitleNode:(HTMLNode *)node
subTextNode:(HTMLNode *)subNode;
#end
Now for the cell we create a NewsItemCell. The code for NewsItemCell might look like the following:
NewsItemCell.h
#interface FSNewsItemCell : UITableViewCell
#property (nonatomic, strong) FSNewsItem *newsItem;
#end
NewsItemCell.m
#interface FSNewsCell ()
#property (nonatomic, strong) UILabel *titleLabel;
#property (nonatomic, strong) UILabel *detailLabel;
#end
#implementation FSNewsItemCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self)
{
self.titleLabel = [[UILabel alloc] init];
[self addSubview:_titleLabel];
self.detailLabel = [[UILabel alloc] init];
[self addSubview:_detailLabel];
}
return self;
}
- (void)layoutSubviews
{
[super layoutSubviews];
const CGRect bounds = self.bounds;
CGFloat width = bounds.size.width - (FS_FLOAT_PADDING * 2) - 15.0f;
_titleLabel.frame = CGRectMake(FS_FLOAT_PADDING, FS_FLOAT_CELL_PADDING_VERTICAL, width, 20.0f);
CGFloat y = _titleLabel.frame.size.height + (FS_FLOAT_CELL_PADDING_VERTICAL * 2);
_detailLabel.frame = CGRectMake(FS_FLOAT_PADDING, y, width, 15.0f);
}
#pragma mark - Private
- (void)setNewsItem:(FSNewsItem *)newsItem
{
if (_newsItem == newsItem)
{
return;
}
_newsItem = newsItem;
self.titleLabel.text = newsItem.title;
if (_newsItem.points && _newsItem.time)
{
self.detailLabel.text = [NSString stringWithFormat:#"%# | %#", _newsItem.points, newsItem.time];
}
else
{
self.detailLabel.text = newsItem.time;
}
[self setNeedsLayout];
}
Finally, when we want to display the news item in the cell, our code would look like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
FSNewsItemCell *cell = (FSNewsItemCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[FSNewsItemCell alloc] initWithStyle:UITableViewCellStylePlain reuseIdentifier:CellIdentifier];
}
cell.newsItem = [_items objectAtIndex:indexPath.row];
return cell;
}
This is in my opinion the cleanest solution and the approach I take most of the time. I like to keep my view controllers small. I also like the fact that my view controller doesn't have to know which controls my (custom) table view cell has. The table view cell gets full responsibility on how to draw itself depending on the data supplied.
I would add a simple data class and put class instances in the NSArray. Or use a NSArray of NSDictionary objects so the items can be addressed by name, not position.
Example class code (classes are very easy these days):
#interface DisplayItems : NSObject
#property (nonatomic, strong) NSString *text;
#property (nonatomic, strong) UIImage *image;
#end
#implementation DisplayItems
#end
One idea is to create a custom class:
#interface CellInfo : NSObject
#property (....) UIImage *image;
#property (....) NSString *text;
#end
Then:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
...
CellInfo *info = [self.cellInfoArray objectAtIndex:indexPath.row];
cell.image = info.image;
cell.text = info.text;
...
}
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];
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.
I am working on my first Objective-C app for iOS and am having an issue with reloading the data in a UITableView.
After reloading the data the cell content will only update when the cell is scrolled above of below the viewable area of the container.
Here is my .h code:
#import <UIKit/UIKit.h>
#import "AFHTTPClient.h"
#import "AFJSONRequestOperation.h"
#interface HelloWorldViewController : UIViewController <UITextFieldDelegate, UITableViewDelegate, UITableViewDataSource>{
NSMutableArray *tableViewArray;
IBOutlet UITableView *tableView;
}
#property (nonatomic, retain) NSMutableArray *tableViewArray;
#property (weak, nonatomic) IBOutlet UILabel *connectionLabel;
#property (nonatomic, retain) IBOutlet UITableView *tableView;
#property (weak, nonatomic) IBOutlet UITextView *textArea;
#property (weak, nonatomic) IBOutlet UITextField *textField2;
#property (weak, nonatomic) IBOutlet UILabel *label;
#property (weak, nonatomic) IBOutlet UITextField *textField;
#property (copy, nonatomic) NSString *userName;
#property (copy, nonatomic) NSString *passWord;
#property (copy, nonatomic) NSMutableString *serverResponse;
- (IBAction)callHome:(id)sender;
#end
and .m code:
#import "HelloWorldViewController.h"
#interface HelloWorldViewController ()
#end
#implementation HelloWorldViewController
#synthesize tableViewArray;
#synthesize connectionLabel;
#synthesize userName = _userName;
#synthesize passWord = _password;
#synthesize serverResponse = _serverResponse;
#synthesize tableView;
#synthesize textArea;
#synthesize textField2;
#synthesize label;
#synthesize textField;
- (void)viewDidLoad
{
[super viewDidLoad];
tableViewArray = [[NSMutableArray alloc] init];
[tableViewArray addObject:#"TEST1"];
[tableViewArray addObject:#"TEST2"];
[tableViewArray addObject:#"TEST3"];
}
- (void)viewDidUnload
{
[self setTextField:nil];
[self setLabel:nil];
[self setTextField2:nil];
[self setTextArea:nil];
[self setTableView:nil];
[self setConnectionLabel:nil];
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
} else {
return YES;
}
}
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
if (theTextField == self.textField) {
[theTextField resignFirstResponder];
}
return YES;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [tableViewArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.textLabel.text = [self.tableViewArray objectAtIndex: [indexPath row]];
return cell;
}
- (IBAction)callHome:(id)sender {
self.userName = self.textField.text;
self.passWord = self.textField2.text;
NSMutableString *tempResponse = [[NSMutableString alloc] initWithFormat:#""];
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:#"http://example.com/"]];
[client setAuthorizationHeaderWithUsername:self.userName password:self.passWord];
[client getPath:#"login.do" parameters:nil
success:^( AFHTTPRequestOperation *operation , id responseObject ){
NSLog(#"Authentication Success: %d", operation.response.statusCode);
self.serverResponse = [NSMutableString stringWithFormat:#"Authentication Success: %d", operation.response.statusCode ];
[tempResponse appendString: self.serverResponse];
self.textArea.text = tempResponse;
}
failure:^(AFHTTPRequestOperation *operation , NSError *error){
NSLog(#"Authentication Error: %#\n%#", error, operation);
}
];
[client getPath:#"test.json.do" parameters:nil
success:^( AFHTTPRequestOperation *operation , id responseObject ){
NSLog(#"Retrieval Success: %d", operation.response.statusCode);
NSDictionary *results = [operation.responseString JSONValue];
NSMutableArray *buildings = [results objectForKey:#"buildings"];
NSMutableArray *names = [[NSMutableArray alloc] init];
for (NSDictionary *building in buildings)
{
[names addObject:[building objectForKey:#"name"]];
}
self.tableViewArray = names;
self.serverResponse = [NSMutableString stringWithFormat:#"\nBuilding List Retrieval Success: %d", operation.response.statusCode ];
[tempResponse appendString: self.serverResponse];
self.connectionLabel.text = tempResponse;
}
failure:^(AFHTTPRequestOperation *operation , NSError *error){
NSLog(#"Retrieval Error: %#\n%#", error, operation);
}
];
NSLog(#"tableView is: %#", [tableView description]);
[tableView reloadData];
}
#end
When I call [self.tableView description]the result is null, but if I call it from cellForRowAtIndexPath then I get the following result:
tableView is: <UITableView: 0x8a71000; frame = (0 0; 280 191); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x6b7e860>; contentOffset: {0, 0}>. Delegate: HelloWorldViewController, DataSource: HelloWorldViewController
Here's a screenshot of interface builder:
All help is appreciated! Thanks!
You're probably not connecting the UITableView in the interface builder..
You have to drag while pressing ctrl from the file's owner to the UITableView and connect it.
Also, you should not access your properties without self, you should do:
#synthesize tableViewArray = _tableViewArray;
and then access it with:
self.tableViewArray
try to avoid accessing your ivars directly, use the property!
Good luck!
It looks like you may have not hooked up your UITableView with the HelloWorldViewController tabelView property in IB.
i tried to follow this tutorial:
http://www.youtube.com/watch?v=L-FK1TrpUng&feature=related
around 00:39:00.
Theres a counter which recognizes every switch to the second view controller and counts it.
The number of view switches should be shown on the second view controller.
But it doesn't work, thats the code:
Test2ViewController.h
#interface Test2ViewController : UIViewController <UITextFieldDelegate> {
UINavigationController *navController;
Test21ViewController *test21View;
NSString *text;
IBOutlet UITextField *textField1;
}
#property(nonatomic, retain) UITextField *textField1;
#property (nonatomic, retain) UINavigationController *navController;
#property (copy) NSString *text;
-(IBAction)pushViewController:(id)sender;
#end
Test2ViewController.m:
#import "Test2ViewController.h"
#import "Test21ViewController.h"
#implementation Test2ViewController
#synthesize textField1, navController, text;
-(IBAction)pushViewController:(id)sender {
static int count = 1;
Test21ViewController *test21ViewController = [[Test21ViewController alloc] init];
[self.navigationController pushViewController:test21ViewController animated:YES];
test21ViewController.label = [NSString stringWithFormat:#"Pushed %d", count];
count++;
}
Test21ViewController.h:
#interface Test21ViewController : UIViewController {
UINavigationController *navController;
NSString *label;
IBOutlet UILabel *textLabel;
UITextField *tF1;
}
#property (copy) NSString *label;
#property (nonatomic, retain) UINavigationController *navController;
#property(nonatomic,retain)UITextField *tF1;
-(IBAction)feldeingabe:(id)Sender;
#end
Test21ViewController.m:
#implementation Test21ViewController
#synthesize label;
- (void)viewDidLoad {
textLabel.text = label;
}
Any ideas why it doesn't work?
Thanks in advance
Code for the second question:
static int count = 1;
Test2ViewController *test2ViewController;
test2ViewController.label = [NSString stringWithFormat:#"Pushed %d !!!!!", count];
[[self navigationController] popViewControllerAnimated:NO];
count++;
CURRENT CODE:
#import "Test21ViewController.h"
#implementation Test21ViewController
#synthesize navController, text, parentView;
-(IBAction)pushViewController2:(id)sender {
Test2ViewController *test2ViewController;
static int count = 1;
test2ViewController.parentView = self;
test2ViewController.label = [NSString stringWithFormat:#"Pushed %d !!!!!", count];
[self.navigationController pushViewController:test2ViewController animated:YES]; count++;
}
For the second problem (passing a string from child to parent);
Test2ViewController.h
#interface Test2ViewController : UIViewController <UITextFieldDelegate> {
NSString *receiverPropertyFromChild;
}
#property(nonatomic, retain) NSString *receiverPropertyFromChild;
Test2ViewController.m:
-(IBAction)pushViewController:(id)sender {
static int count = 1;
Test21ViewController *test21ViewController = [[Test21ViewController alloc] init];
test21ViewController.label = [NSString stringWithFormat:#"Pushed %d", count];
test21ViewController.parentView = self;
[self.navigationController pushViewController:test21ViewController animated:YES];
count++;
}
Test21ViewController.h:
#class Test2ViewController;
#interface Test21ViewController : UIViewController {
Test2ViewController *parentView;
}
#property (nonatomic, assign) Test2ViewController *parentView;
Test21ViewController.m
-(IBAction)goToTest2ViewController:(id)sender {
parentView.receiverPropertyFromChild = #"the text you want to pass";
[self.navigationController popViewControllerAnimated:YES];
count++;
}
can you try:
Test21ViewController *test21ViewController = [[Test21ViewController alloc] init];
test21ViewController.label = [NSString stringWithFormat:#"Pushed %d", count];
[self.navigationController pushViewController:test21ViewController animated:YES];
I swapped the last two lines. It could be that you are setting the label after viewDidLoad has already been called, thus not setting the value in the label.
That said, it is better to pass the string as an init parameter, not as a property and then set in viewDidLoad.
edit:
To set it as init parameter, you need to create a new init method to accept that parameter.
- (id) initWithString:(NSString *)labelParam {
self = [super init];
if (self) {
this.label = labelParam;
}
return self;
}