I am trying to create an iphone application that reads a json feed and I am having some trouble updating a TableView.
This is my TableViewController header file:
#interface LiveNewsController : UITableViewController <UITableViewDelegate, UITableViewDataSource>{
NSMutableData *responseData;
NSMutableArray *articleArray;
UITableView *tblView;
}
-(void) refreshPressed: (id)sender;
#property (nonatomic, retain) IBOutlet UITableView *tblView;
#end
These are some parts of my TableViewController implementation file:
#implementation LiveNewsController
#synthesize tblView;
-(id) init {
if(self = [super init])
{
self.title = #"Live News";
}
return self;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"I am here %d",[articleArray count]);
return [articleArray count];
}
// Customize the appearance of table view cells.
- (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];
}
NSLog(#"cellForRowAtIndexPath called. Data size %d", [articleArray count]);
NSUInteger row = [indexPath row];
cell.textLabel.text = [articleArray objectAtIndex:row];
return cell;
}
-(void) refreshPressed: (id)sender
{
NSLog(#"Reload Pressed. Data size: %d", [articleArray count]);
[tblView reloadData];
}
Here is a screenshot of my .xib file with the connections:
So the main idea is the following:
Fetch articleArray
When refresh is pressed update view (the data is being fetched correctly but the snippet doesn't show it here)
numberOfRowsInSection and CellForRowAtIndexPath are only being called once when the view loads but nothing happens when I press the reload button.
I checked tblView and it is nil. I did some research and read that this is usually caused by some erroneous connections in the .xib file but I have triple checked that and I can't seem to pinpoint the problem.
Any help is appreciated,
Thanks!
You don't need to declare the UITableView tblView, the UITableViewController has already one (and therefore all subclasses too).
Just try [self.tableView reloadData];.
Related
In my app I allow users to add new rows of NSStrings to a UITableView. I save these new strings in an NSMutableArray *dataArray
So for numberOfRowsInSection I return [dataArray count], but it seems to just return 0 all the time so my table is not auto-populating.
If it helps, when I do an NSLog of [dataArray count] as a add more entries, it keeps remaining as 0. Why isn't it increasing?
Any help?
Without looking # your code ,it's not possible to predict the reason..
Then also you can try your HardLuck...below:
First try to NSLog your dataArray to check wether the record is adding in that or not.
It's its ok... you are getting the records.
then you are missing one thing.
reload the table..
[tableView reloadData];
I think this would definitely help you..otherwise put some code over here.
Have you initialised your Array. Here is how I've done it - prob a better way!
.h:
#interface RootViewController : UITableViewController {
NSArray *array;
}
#property (nonatomic, retain) NSArray *array;
#end
.m:
#implementation RootViewController
#synthesize array;
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableArray *mArry = [[NSMutableArray alloc] init];
[mArry addObject:#"An ObecjT"];
self.array = mArry;
[mArry release];
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [array count];
}
// Customize the appearance of table view cells.
- (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];
}
// Configure the cell.
cell.textLabel.text = [array objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSMutableArray *aNewArray = [[NSMutableArray alloc] initWithArray:array];
[aNewArray addObject:#"Your Object"];
self.array = aNewArray;
[aNewArray release];
[self.tableView reloadData];
}
- (void)viewDidUnload {
self.array = nil;
}
- (void)dealloc {
[array release];
[super dealloc];
}
Did you set the delegate for the UITableView in Interface Builder ? please check it.
If you have added, then you have to check with that dataArray whether it is having records or not.
This question is related to UITableView issue when using separate delegate/dataSource, though I have a different problem. I'm just starting to learn iPhone programming.
Basically I have one main view with a table. On the event of a cell click, a sub view with another table is shown.
The datasource and delegate for the main view's table are set as files' owner, and I have added the necessary code in there to handle the table data and everything is fine.
But, when the second table in the sub-view seems to crash the application, I did the same thing, set the datasource and delegate to the file's owner and repeated the same procedure as for the main view's table. I have no idea why this is happening.
The sub-view has its only nib/xib file and its own outlet. If i do not attach any datasource to the subview's table, it takes the data from the main view's table; I don't understand why that is, since I have set the datasource to be the file's owner.
For example: the FirstView controller has a table FirstTable, the datasource and delegate are set to the owner of Files. I added the following in FirstView.m:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 4;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"LibraryListingCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text =#"Table Cell";
return cell;
}
Everything works perfectly.
The moment I repeat this with a second table and a second view, the application crashes saying
reason: '-[UISectionRowData tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x69188d0'
I have done exactly the same for second table: implemented numberOfRowsInSection and cellForRowAtIndexPatch inside secondview.m and set the second table's delegate and datasource to the file's owner. If I remove the delegate and datasource for the second table, the application doesn't crash but has an empty table in the second view.
Any suggestions? or am I missing some key concept here ?
You can use same datasource and delegate methods for multiple tables.
You have to mention in which table you are doing operations.
For example:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([tableView isEqual:TableView1])
{
//do work for tableview1
}
else if([tableView isEqual:TableView2])
{
//do operations for tableview2
}
}
This is the main View controller .h file.
#import <UIKit/UIKit.h>
#import "SubView.h"
#interface StackOverTableSubViewViewController : UIViewController <UITableViewDelegate,UITableViewDataSource>
{
UIView *contentView;
UITableView *tblVw;
NSMutableArray *array;
SubView *SubViewObj;
}
#property(nonatomic,retain) UIView *contentView;
#property(nonatomic,retain) UITableView *tblVw;
#property(nonatomic,retain) NSMutableArray *array;
#property(nonatomic,retain) SubView *SubViewObj;
#end
This is the main View controller .m file.
#import "StackOverTableSubViewViewController.h"
#implementation StackOverTableSubViewViewController
#synthesize contentView,tblVw,array,SubViewObj;
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView
{
contentView=[[UIView alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
contentView.autoresizingMask=(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
contentView.autoresizesSubviews=YES;
contentView.backgroundColor=[UIColor whiteColor];
tblVw=[[UITableView alloc]initWithFrame:[[UIScreen mainScreen]bounds] style:UITableViewStylePlain];
tblVw.dataSource=self;
tblVw.delegate=self;
tblVw.scrollEnabled=YES;
array=[[NSMutableArray alloc]init];
[array addObject:#"Row1"];
[array addObject:#"Row2"];
[array addObject:#"Row3"];
[array addObject:#"Row4"];
[array addObject:#"Row5"];
[array addObject:#"Row6"];
[array addObject:#"Row7"];
[array addObject:#"Row8"];
[array addObject:#"Row9"];
[array addObject:#"Row10"];
[array addObject:#"Row11"];
[array addObject:#"Row12"];
[contentView addSubview:tblVw];
self.view=contentView;
}
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section
{
return [array count];
}
// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
// Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CellIdentifier";
// Dequeue or create a cell of the appropriate type.
// UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryNone;
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.textLabel.numberOfLines = 0;
[cell.textLabel sizeToFit];
}
cell.textLabel.text=[array objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
SubViewObj=[[SubView alloc]init];
[self.view addSubview:SubViewObj.view];
}
/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
}
*/
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[contentView release];
[SubViewObj release];
[tblVw release];
[array release];
[super dealloc];
}
#end
Add a view controller called subview. Here's subview.h:
#import <UIKit/UIKit.h>
#interface SubView : UIViewController <UITableViewDelegate,UITableViewDataSource>
{
UIView *contentView;
UITableView *tblVw;
NSMutableArray *array;
}
#property(nonatomic,retain) UIView *contentView;
#property(nonatomic,retain) UITableView *tblVw;
#property(nonatomic,retain) NSMutableArray *array;
#end
And subview.m:
#import "SubView.h"
#import
#implementation SubView
#synthesize contentView,tblVw,array;
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
contentView=[[UIView alloc]initWithFrame:CGRectMake(200, 10, 300, 600)];
contentView.autoresizingMask=(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
contentView.autoresizesSubviews=YES;
contentView.backgroundColor=[UIColor whiteColor];
tblVw=[[UITableView alloc]initWithFrame:CGRectMake(200, 10, 300, 600) style:UITableViewStylePlain];
tblVw.dataSource=self;
tblVw.delegate=self;
tblVw.scrollEnabled=YES;
tblVw.layer.borderWidth=4.0;
tblVw.layer.borderColor=[[UIColor redColor]CGColor];
array=[[NSMutableArray alloc]init];
[array addObject:#"Data1"];
[array addObject:#"Data2"];
[array addObject:#"Data3"];
[array addObject:#"Data4"];
[array addObject:#"Data5"];
[array addObject:#"Data6"];
[array addObject:#"Data7"];
[array addObject:#"Data8"];
[array addObject:#"Data9"];
[array addObject:#"Data10"];
[array addObject:#"Data11"];
[array addObject:#"Data12"];
[contentView addSubview:tblVw];
self.view=contentView;
}
/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
}
*/
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section
{
return [array count];
}
// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
// Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CellIdentifier";
// Dequeue or create a cell of the appropriate type.
// UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryNone;
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.textLabel.numberOfLines = 0;
[cell.textLabel sizeToFit];
}
cell.textLabel.text=[array objectAtIndex:indexPath.row];
return cell;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
return YES;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
#end
Try this code. This app was done for the iPad. Change the dimensions as needed for the iPhone.
I had the EXACT same issue and fixed it by deleting my connection from the table view's datasource to the files owner. Then I pasted in the code below replacing the existing cellForRowAtIndexPath. I had to change the array name to match my array and then reconnect the datasource to the files owner, and it started working. Must have been a snafu in my function code somewhere.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CellIdentifier";
// Dequeue or create a cell of the appropriate type.
// UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryNone;
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.textLabel.numberOfLines = 0;
[cell.textLabel sizeToFit];
}
cell.textLabel.text=[array objectAtIndex:indexPath.row];
return cell;
}
Is this possible? I just want a small table in my current view... here is what I'm trying to do:
.h file
#import <UIKit/UIKit.h>
#interface IngredientsRootView : UIViewController <UITableViewDelegate, UITableViewDataSource> {
UITableView *ingredientsTable;
}
#property (nonatomic, retain) UITableView *ingredientsTable;
#end
.m file I have delegate and data source methods and this code:
ingredientsTable = [[UITableView alloc] initWithFrame:CGRectMake(10, 10, 300, 300) style:UITableViewStylePlain];
[ingredientsTable setDelegate:self];
[ingredientsTable setDataSource:self];
[self.view addSubview:ingredientsTable];
The app doesn't crash, but it doesn't show a table. At the moment I have just set everything definitely as per:
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return 10;
}
// the appearance of table view cells.
- (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];
}
// Configure the cell...
cell.textLabel.text = #"Hello";
return cell;
}
What am I doing wrong? Thanks
Try calling -reloadData on the table view after adding it as a subview.
Also, how is the view set up? Is it created in a XIB or via -loadView?
Did you remembered to add the [window addSubview:[IngredientsRootView view]]; to your app delegate ?
And by the way, instead of inheriting from UIViewController you can just inherit from UITableViewController and you'll get all that functionality for you with no added code.
I've subclassed UITableView to create my own data retrieval system, as described in Apple's own Core Data tutorial, but I've hit a problem. The substitute cellForRowAtIndexPath method in my custom table never gets called, not even when I call reloadData or setNeedsDisplay. I've been hunting around for solutions to this one, and it seems that this error can be caused by a multitude of problems. However I've checked all the ones I can find and cannot see anything missing. Can anyone tell me what's likely to be wrong?
P.S. I know the UITableViewDataSource protocol needs to be in triangular brackets, but I couldn't find out how to show triangular brackets on the page without deleting the text between them.
H-File
#interface DataTable : UITableView <UITableViewDataSource> {
NSMutableArray *list;
}
#property (nonatomic, retain) NSMutableArray *list;
#end
M-File
#implementation DataTable
#synthesize list;
-(id) initWithFrame:(CGRect)rect Style:(UITableViewStyle)style{
if (self = [super initWithFrame:rect style:style]){
list = [[NSMutableArray alloc] init];
self.dataSource = self;
}
return self;
}
(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [list count];
}
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellID = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if (cell == nil){
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:cellID] autorelease];
}
CH *this = (CH *)[list objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [this.clusterName mutableCopy];
return cell;
}
-(void) dealloc{
[list release];
[super dealloc];
}
#end
Never mind, think I've found it. Basically, you can't set the datasource delegate in that part of the program. Need to do it from its owning view controller.
I'm new to iPhone application development. I'm trying to understand how to use UITableView.
I'm wrote simple code:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1 ;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease];
}
cell.textLabel.text = #"Hello";
return cell;
}
UITable shows content, but if i'm drag table contents my application terminates. You can see video: http://www.youtube.com/watch?v=TucTVJVhSD0
I tried to everything with array:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1 ;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [hello count] ;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease];
}
cell.textLabel.text = [hello objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:NO];
NSLog(#"Selected") ;
}
- (void) awakeFromNib
{
hello = [[NSArray alloc] initWithObjects:#"hello", #"world", #"end", nil];
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
}
Content is shown and if I'm selecting item I'm getting:
[Session started at 2010-03-16 19:21:48 +0200.]
2010-03-16 19:21:52.295 ViewTest[1775:207] *** -[ViewTestViewController respondsToSelector:]: message sent to deallocated instance 0x3911ec0
I'm total new to iPhone programming. And as I see everything I do - I'm just getting application terminated ..
Your table view code looks fine. Did you implement any other delegate methods in the ViewTestViewController?
Try running the application in the debugger. When it crashes, look at the stack trace. It should give a better hint.
(1) I think you may have released your tableview controller instance and killed it while it was still in use so that when the tableview sends it one of its delegate or datasource messages it crashes.
(2) Alternatively, the error message says that you are attempting to send the respondsToSelector: message to an instance of ViewTestViewController when you should be sending it to the class. (-[ViewTestViewController respondsToSelector:] vs + [ViewTestViewController respondsToSelector:] the "-" and "+" make all the difference.)
So, somewhere in your code, probably your app delegate, you've got code that says:
ViewTestViewController *myTableViewController= //..however you setup the controller
[myTableViewController respondsToSelector:#selector(someMethod)];
...when you should have...
[ViewTestViewController respondsToSelector:#selector(someMethod)];
I think (1) the most likely.
Thanks to all. I found problem. I found i haven't connected viewController IBOutlet with App Delegate. But why View was shown ?
#interface ViewTestAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
ViewTestViewController *viewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet ViewTestViewController *viewController;