I can't find a simple, concise answer anywhere and I refuse to believe that XCode makes things as hard as other tutorials I've found out there...
Say I have the following array
NSArray* days = [NSArray arrayWithObjects:#"Sunday",#"Monday",#Tuesday",#"Wednesday",#"Thursday",#"Friday",#"Saturday",nil];
I have a UI Table View, table_Days, that I would like to simply show the items from my array. What is the proper way to go about populating my table?
Here's my full explanation, starting with a case extremely similar to yours:
http://www.apeth.com/iOSBook/ch21.html#_table_view_data
So suppose days is stored as an instance variable accessed through a property self.days. Then set self as the table view's datasource and use this code:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (!self.days) // data not ready?
return 0;
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
return [self.days count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:#"Cell"
forIndexPath:indexPath];
cell.textLabel.text = (self.days)[indexPath.row];
return cell;
}
You should populate your table view using the data source methods. Returning the count of the array for the number of rows.
If you need to detect when a user taps on a cell you can use the delegate methods.
#interface ViewController<UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, copy) NSArray *days;
#property (nonatomic, strong) UITableView *tableDays;
#end
#implementation ViewController
-(void)viewDidLoad
{
[super viewDidLoad];
UITableView *tableDays; // Set this up
[tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"Cell"];
tableDays.delegate = self;
tableDays.dataSource = self;
[self.view addSubview:tableDays];
self.tableDays = tableDays;
self.days = #[#"Sunday", #"Monday", #"Tuesday", #"Wednesday", #"Thursday", #"Friday", #"Saturday"];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.days count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.textLabel.text = self.days[indexPath.row];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *day = self.days[indexPath.row];
NSLog(#"Day tapped: %#", day);
}
#end
You should consider using a UITableViewController if you just want to show a table view.
Note that its better practice to use camel case for variables.
Related
Please if you are going to add the link of the documentation, please don't do that
I have a problem her and i don't know how to solve it and need a clear answer
I have build a table view from xcode UI and add 5 sections each section contains some cells except section2, what I want to do is to add cells to section2 in viewDidLoaded is that possible or not
this is the header file
#interface Menu : UITableViewController;
this is the implementation file
#implementation Menu
#synthesize drawerTableView;
- (void) viewDidLoad {
NSDictionary *object = [drawerTableView dataSource];
KhawaterDataManager *sharedManager = [KhawaterDataManager instance];
CategoriesResponse *categories = [sharedManager categories];
[categories printObject];
}
/*- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"%d", section);
switch (section) {
case 1:
return 5;
break;
}
return [tableView.dataSource[section] count];
}*/
/*- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
[cell setBackgroundColor:[UIColor colorWithRed:.8 green:.8 blue:1 alpha:1]];
cell.textLabel.text = #"hello";
return cell;
}*/
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)newIndexPath{
// my logic
}
#end
I think you are using static cells in your UITableView. What you can do is make use of dynamic tableview cells. You have to uncomment and use both methods to create your cell:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
I a UITableView called tableView. It's data array called namesArray.
I have a function that adds a name to the array that looks like this:
-(void)addName:(NSString*)name
{
[self.namesArray addObject: name];
[self.tableView reloadData];
}
After I call reloadData on tableView, the last cell (the one that was added) is not showing on tableView, numberOfRowsInSection return the actual number so there is a space for another cell but there is not an actual cell.
I was debugging cellForRowAtIndexPath and I was found out that when cellForRowAtIndexPath called for the new cell, dequeueReusableCellWithIdentifier returns nil while when it called to the other cells (except when indexPath.row == 0 of course) it returns a cell.
The code for cellForRowAtIndexPath:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier=#"Cell";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text=[self.namesArray objectAtIndex:indexPath.row];
return cell;
}
numberOfRows:
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.namesArray.count;
}
Note: if I try to print the last object of namesArray using NSLog it's looking fine (the last object is the new one that was created) so it's a problem with reloading the data of tableView
Can you please help me? Thanks!
check the number of rows you returns in numberOfRowsInSection
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
it should be something like:
[self.namesArray count];
First dataSource and delegate the tableview. after that make sure using below method with perfection
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [your array count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier=#"Cell";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text=[self.namesArray objectAtIndex:indexPath.row];
return cell;
}
After that reload tableView with
[_tableViewName reloadData];
-(void)addName:(NSString*)name
{
[self.namesArray addObject: name];
[self.tableView reloadData];
}
If you are calling this function again and again to fill the array then, do not reload tableview in this method. Because, its getting reloaded overtime you call this method and cellForRowAtIndexPath gets called every time. So, after your array gets filled completely then, reload the tableview
.h
#interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>
{
IBOutlet UITextField *txtName;
IBOutlet UITableView *tableObject;
NSMutableArray *namesArray;
}
- (IBAction)btnAdd:(UIButton *)sender;
.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
namesArray = [[NSMutableArray alloc] init];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
{
return namesArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
static NSString *cellIdentifier=#"Cell";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text=[namesArray objectAtIndex:indexPath.row];
return cell;
}
-(void)addName:(NSString*)name
{
[namesArray addObject: name];
[tableObject reloadData];
}
- (IBAction)btnAdd:(UIButton *)sender {
[self addName:txtName.text];
}
I am creating an application for IOS and am struggling with accessing an object inside an array i have made for display on the table view cell.
This is the code i have used to add the object to the array every time the loop cycles through.
for (int i = 0; i < [parsedArray count]; i++) {
HPTBusStops *busStops = [[HPTBusStops alloc] init];
NSArray *informationArray = [parsedArray objectAtIndex:i];
busStops.busStopNumber = [informationArray objectAtIndex:0];
busStops.busStopName = [informationArray objectAtIndex:1];
busStops.latitude = [informationArray objectAtIndex:2];
busStops.longitude = [informationArray objectAtIndex:3];
[self.busStopsHolder addObject:busStops];
}
The HPTBusStops class is obviously custom, and later in the master view controller, i am tring to re-access these properties through the busStopsHolder array, when programming the cell, in this part:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
HPTBusStopsTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"BusStopCell" forIndexPath:indexPath];
return cell;
}
I am honestly very unsure of how to access the busStops object's properties through the busStopHolder's array.
Any help would be appreciated
Thanks
Hamish
It looks to me like you might have an issue with scope...
You'll need to make "busStopsHolder" a #property of the class containing the for loop and instantiate that class as an instance variable in your Master View Controller.
in your class, say MyInfoClass.h:
#property (strong, nonatomic) NSMutableArray *busStopsHolder;
in MyInfoClass.m:
synthesize busStopsHolder;
Make sure you have initialized your busStopsHolder array in MyInfoClass...
(id) init {
busStopsHolder = [[NSMutableArray alloc] init];
}
Then in your master view controller .h:
#import "MyInfoClass.h"
#interface myMastserViewController : UIViewController {
MyInfoClass *infoClass;
}
Then...
- (void) viewDidLoad {
infoClass = [[MyInfoClass alloc] init];
[infoClass methodToLoadBusStops];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
HPTBusStopsTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"BusStopCell" forIndexPath:indexPath];
HPTBusStop *busStop = [[infoClass busStopsHolder] objectAtIndex:indexPath.row];
[[cell textLabel] setText:[busStop busStopName]]
return cell;
}
An oversimplified way to do this is as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
HPTBusStopsTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"BusStopCell" forIndexPath:indexPath];
HPTBusStops *busStops = yourSourceArray[indexPath.row];
cell.textLabel.text = busStops.name;
return cell;
}
If your tableView has one section, you can use the tableView's indexPath.row property to determine which index you're dealing with, use that as the index to access the relevant object in your source array, and then customize the cell based on the specific object at that index. In the example code I just assumed there was a name property on the busStops object for example purposes.
Make sure in your numberOfRowsInSection method you set the number of rows as the number of objects in your source array, whatever that is.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return yourSourceArray.count;
}
When I click on a cell in my tableview, the app crashes with:
// QuestionViewController.h
#interface QuestionViewController : UIViewController <UITableViewDelegate , UITableViewDataSource> {
}
#property (nonatomic, strong) AppDelegate *app;
#property (nonatomic, retain) PFObject *feed;
#end
// QuestionViewController.m
#synthesize app, feed;
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section
{
return [[feed objectForKey:#"options"] count];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSString *cellTxt = [[[feed objectForKey:#"options"] objectAtIndex:indexPath.row] objectForKey:#"option_text"];
[[cell textLabel] setText:cellTxt];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"clicked cell");
}
- (void)viewDidLoad {
[super viewDidLoad];
app = [[UIApplication sharedApplication]delegate];
feed = [app.feed objectAtIndex:0];
}
I have implemented didSelectRowAtIndexPath, but it doesn't get called before crashing.
Other threads on SO suggest that I have unconnected outlets but I have checked that this isn't the case.
I am creating multiple instances of the above UIViewController like this:
for (int a = 0; a < totalQuestions; a++) {
QuestionViewController *temp = (QuestionViewController *)[self.storyboard instantiateViewControllerWithIdentifier:#"aQuestion"];
temp.view.frame = CGRectMake(self.view.frame.size.width*a+scrollWidthBeforeAppend, 0, 320, 443);
[scroller addSubview:temp.view];
}
And adding them to a scroll view. They display correctly, the UITableView is populated, and everything seems to work fine other than when I try and click on a cell. Any suggestions?
Your temp UIViewControllers get deallocated by the time you press a cell.
You should keep a reference to them to prevent this, for example in an array.
This is the first time im trying to set a UITableView delegate/datasource to an instance of an object.
I have a UIView managed by a class called hMain, and a UITableView inside of main managed by an instance of a class called vTable.
hMain.h:
#interface hMain : UIViewController
#property (strong, nonatomic) IBOutlet vTable *voteTbl;
#end
hMain.m:
- (void)viewDidLoad
{
[super viewDidLoad];
voteTbl = [[vTable alloc]init];
[self.voteTbl setDelegate:voteTbl];
[self.voteTbl setDataSource:voteTbl];
}
vTable.h:
#interface vTable : UITableView <UITableViewDelegate , UITableViewDataSource>
#end
vTable.M:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [UITableViewCell configureFlatCellWithColor:[UIColor greenSeaColor] selectedColor:[UIColor wetAsphaltColor] reuseIdentifier:CellIdentifier inTableView:(UITableView *)tableView];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
[cell configureFlatCellWithColor:[UIColor greenSeaColor] selectedColor:[UIColor wetAsphaltColor]];
}
cell.textLabel.text = #"Hello there!";
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Row pressed!!");
}
This is really my first time straying away from IB and doing things programatically so im not sure im settings delegates and things correctly. This is also my first attempt and setting a delegate/datasource outside of self.
My problem is the table is coming out blank every time.
What is vTable? Looks like you have a "voteTable" class (BTW: classes should start with an uppercase char, instance variables should start with lowercase). Anyhow, looks like your main problem is you forgot to add the table as a subview and set its frame. eg:
self.voteTbl = [[VoteTable alloc] init];
self.voteTbl.delegate = self;
self.voteTbl.dataSource = self;
self.voteTbl.frame = self.view.bounds;
[self.view addSubView:self.voteTbl];