Which method is better / cleaner? - objective-c

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;
...
}

Related

UITableview - Can't Reload data

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

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.

Error: variable is not a CFArray

I am trying to create custom UITableViewCells, following this article. I add outlets for three fields in the cell. I am taking data stored in an NSMutableArray and placing them in the custom cell labels. When debugging, I can see the data in the source array elements, but this is in the cell labels: "variable is not a CFArray". Obviously it's not working... here is the code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"--> cellForRowAtIndexPath");
static NSString *CellIdentifier = #"siteTableCell";
SiteListingsCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[SiteListingsCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
// Configure the cell...
cell.staLabel.text = [self.staLabels objectAtIndex: [indexPath row]];
cell.descLabel.text = [self.descLabels objectAtIndex:[indexPath row]];
cell.dateLabel.text = [self.dateLabels objectAtIndex:[indexPath row]];
return cell;
}
This is the definition of the labels:
#interface SiteListingsCell : UITableViewCell {
}
#property (nonatomic, strong) IBOutlet UILabel *staLabel;
#property (nonatomic, strong) IBOutlet UILabel *descLabel;
#property (nonatomic, strong) IBOutlet UILabel *dateLabel;
#end
This is the definition of sArray:
#interface sArray : NSObject { // class (struct) to hold site information
}
#property (nonatomic, readwrite) NSString *sSiteID;
#property (nonatomic, readwrite) NSString *sInitialSTA;
#property (nonatomic, readwrite) NSString *sElev;
#property (nonatomic, readwrite) NSString *sJobDesc;
#property (nonatomic, readwrite) NSString *sJobDate;
#end
UPDATE: This code gets called when I want to fill sArray and move the values to the custom cell labels:
- (void) displaySites {
NSLog(#"displaySites");
// get list of sites and place them in sArray
slSQLite *dbCode = [[slSQLite alloc] init];
[dbCode getListOfSites];
// put site data into array for display
NSLog(#"\n2-The array listOfSites contains %d items", dbCode.listOfSites.count);
// sArray *sa = [[sArray alloc] init]; // initialize sArray object
for(int i = 0; i <dbCode.listOfSites.count; i++) {
sArray *sa = [dbCode.listOfSites objectAtIndex:i]; // get the sArray out of listOfSites
staLabels = sa.sSiteID;
descLabels = sa.sJobDesc;
dateLabels = sa.sJobDate;
}
return;
}
How do I fix this so it works?
Try to do:
staLabels.text = sa.sSiteID;
ect...

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;