I have a UITableView in next segue when a button is pressed. The code that i have implemented in the implementation file is as follows. The view is shifting, but the data is not loading in the view.
What could be the problem?
- (void)viewDidLoad
{
[super viewDidLoad];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData* data = [NSData dataWithContentsOfURL:
[NSURL URLWithString: #"https://api.twitter.com/1/statuses/public_timeline.json"]];
NSError* error;
tweets = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:&error];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
});
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (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 the number of sections.
return 0;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return tweets.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TweetCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSDictionary *tweet = [tweets objectAtIndex:indexPath.row];
NSString *text = [tweet objectForKey:#"text"];
NSString *name = [[tweet objectForKey:#"user"] objectForKey:#"name"];
cell.textLabel.text = text;
cell.detailTextLabel.text = [NSString stringWithFormat:#"by %#", name];
return cell;
}
(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 0;
}
Don't you need at least 1 section?
You should use breakpoints in the debugger to break on the numberOfRowsInSection method and cellForRowAtIndexPath to verify that your data is being parsed and handled correctly. If you're unfamiliar with breakpoints now is a good chance to get to know them - they are invaluable in debugging and resolving problems.
As a general note, you probably shouldn't be using dataWithContentsOfURL to do your networking. It's not really designed for that usage. NSURLConnection is a much better option, which will give you far more flexibility.
dyspatch_async
is named is as because it's asynchronous. You seem to be thinking that the second call to it is executed after the first call - but no. They're executes parallel, and because the URL operation is slower, the table view's update occurs when there's no data yet.
Solution: put the reloadData call in the same block as the URL operation - you don't need two separate calls to dispatch_async.
Also, you return 0 from
numberOfSectionsInTableView:
so the table doesn't even look for data. Return 1.
Related
I'm trying to create an iOS app in which I must have a UITableView that every time I press a new entry button, a newcell appears with the time when I pressed that button. My problem is that everytime I press the buttons, not only the cell which is created displays the current time, but the cells above it, which were showing a different time, reload and also show the current time. To try and explain it better, if I press the button at 8:05, 9:01 and 9:10, i want the UITableView to show:
-8:05
-9:01
-9:10
Instead, it's showing:
-9:10
-9:10
-9:10.
What do I do?? Thanks
Here's my code ( newEntry is the button and brain is an object where I have the method to get the current time)
#implementation MarcaPontoViewController{
NSMutableArray *_entryArray;
#synthesize brain=_brain;
- (void)viewDidLoad
{
[super viewDidLoad];
_brain = [[Brain alloc] init];
_entryArray = [[NSMutableArray alloc] init];
//[self updateTime];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [_entryArray count];
}
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier= #"myCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [_entryArray lastObject];
}
return cell;
}
- (IBAction)newEntry:(id)sender {
[_entryArray addObject:[self.brain currentTime]];
[_timeTable reloadData];
}
#end
Your problem is here in this line :
cell.textLabel.text = [_entryArray lastObject];
You need to use :
cell.textLabel.text = [_entryArray objectAtIndex:indexPath.row];
Or,
cell.textLabel.text = _entryArray[indexPath.row];
[_entryArray lastObject] always gives the last returned object.
Use
cell.textLabel.text = [_entryArray objectAtIndex: indexPath.row];
The line cell.textLabel.text = [_entryArray lastObject] will only ever return the last object in the array, which is why you are seeing the same time repeated. Change this to:
// in cellForRowAtIndexPath:
cell.textLabel.text = [_entryArray objectAtIndex:indexPath.row];
This should fix the underlying problem.
I am calling a WCF service to display data in a UITableViewController.The code in the .m file is:
- (void)viewDidLoad
{
[super viewDidLoad];
[docTable setDataSource:self];
[docTable setDelegate:self];
}
-(void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
EDViPadDocSyncService *service = [[EDViPadDocSyncService alloc]init];
EDVCategory *cat = [EDVCategory alloc];
cat.categoryId = [catId intValue];
[service getDocsByCatId:self action:#selector(getDocsByCatIdHandler:) category:cat];
[docTable reloadData];
}
- (void) getDocsByCatIdHandler: (id)value
{
if([value isKindOfClass:[NSError class]])
{
NSLog(#"%#", value);
return;
}
if([value isKindOfClass:[SoapFault class]])
{
NSLog(#"%#", value);
return;
}
NSMutableArray* result = (NSMutableArray*)value;
NSMutableArray *documentList = [[NSMutableArray alloc] init];
self.myDocList = [[NSMutableArray array] init];
for (int i = 0; i < [result count]; i++)
{
EDVDocument *docObj = [[EDVDocument alloc]init];
docObj = [result objectAtIndex:i];
[documentList addObject:[docObj docName]];
}
self.myDocList = documentList;
[docTable reloadData];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int cnt = [self.myDocList count];
NSLog(#"ABC=%#",cnt);
return [self.myDocList count];
//return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
DocumentCell *cell = [tableView dequeueReusableCellWithIdentifier:#"DocumentCell"];
if (cell == nil)
{
cell = [[[DocumentCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"DocumentCell"] autorelease];
}
NSLog(#"cell text=%#",[self.myDocList objectAtIndex:indexPath.row]);
cell.lblDocName.text = [self.myDocList objectAtIndex:indexPath.row];
return cell;
}
I am using storyboard.I have hooked the "docTable",set the datasource and the delegate for "docTable".The problem is,the service is called after the call to "numberOfRowsInSection".So,'return [self.myDocList count]' is 0.I have put [docTable reloadData] in viewWillAppear as well as in the service handler,that is,"getDocsByCatIdHandler".But it isn't getting reloaded,as expected.Is there anything else I can try? EDIT:- This a Master-Detail application.I have used the same code for loading data in the "MasterViewController" UITableViewController and it works.When the user selects a cell in this table,I need to populate data in the second tableview by calling the WCF service.The second tableview isn't displaying data.
Everything looks good which leads me to believe you are not getting the results from the webservice you are expecting.
One small thing first thats not your problem. If result is in fact an array and there is an object in it, you shouldnt need to alloc a new EDVDocument.
EDVDocument *docObj = [result objectAtIndex:i];
Can you log the (id)value parameter to see what we're working with?
NSLog(#"%#", value);
If value is not an array, the cast wont complain, it will just work by not working. However, if it is an array you may be finding trouble with assigning your property (granted I dont know how its declared) to a local array. You can use the following function to create a new array with the elements of your temporary array;
self.myDocList = [[NSArray alloc] initWithArray:documentList];
[docTable reloadData];
I hope this helps.
I was facing the same issue when i have a async webService call. I was using a private Library to call webservice so my control goes to the library and after the response comes a method in Appdelegate is set as handler. So what you need to do is before calling the Webservice save the state of tableview in a shared variable and after you have received response set it back to tableView and then call the reload method. Something like below:
SharedView.tblView = self.tableView;
[webservice Call];
After Response:
self.tableView = SharedView.tblView;
[self.tableView reloadData];
Hope This Helps.
So, i have UITableView, large amount of data which is displayed with a many rows, and i want to make sections (like default contacts application and its sections). So there is my code (listViewController.m file):
#import "FailedBanksListViewController.h"
#import "FailedBankDatabase.h"
#import "FailedBankInfo.h"
#import "FailedBanksDetailViewController.h"
#import "BIDAppDelegate.h"
#implementation FailedBanksListViewController
#synthesize failedBankInfos = _failedBankInfos;
#synthesize details = _details;
- (void)viewDidLoad {
self.view.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:#"3.png"]];;
[super viewDidLoad];
self.failedBankInfos = [FailedBankDatabase database].failedBankInfos;
self.title = #"Продукты";
}
- (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;
self.failedBankInfos = nil;
self.details = nil;
}
- (void) viewWillAppear:(BOOL)animated
{
}
#pragma mark Table view methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [_failedBankInfos count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [_failedBankInfos 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:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// Set up the cell...
FailedBankInfo *info = [_failedBankInfos objectAtIndex:indexPath.row];
cell.textLabel.text = info.name;
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#, %#", info.city, info.state];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (self.details == nil) {
self.details = [[FailedBanksDetailViewController alloc] initWithNibName:#"FailedBanksDetailViewController" bundle:nil];
}
FailedBankInfo *info = [_failedBankInfos objectAtIndex:indexPath.row];
_details.uniqueId = info.uniqueId;
[self.navigationController pushViewController:_details animated:YES];
}
- (void)dealloc {
self.failedBankInfos = nil;
}
#end
With your code you should have multiple sections (each one exactly equal than the others).
The idea for a multiple section table view is (normally) to have a 2 dimensional array (not 1 dimensional as is your case). Then each row would represent a section for your table view.
For example, if you have an array structured this way (and I know you can't initialize it this way):
arr = {
{'apple','orange','banana'},
{'CD-Rom', 'DVD', 'BR-Disk'},
{'AK-47', 'Rocket launcher', 'Water gun'}
}
your number of sections method may return [arr count] and the number of rows for section s may return [[arr objectAtIndex:s] count]. And remember that you can set the title for each section with the table view datasource method tableView:titleForHeaderInSection:.
If you want to load the info from a SQLite DB, nothing may change. It's exactly the same but you will have to keep of the way to get your data.
When you thing you understand all this stuff then checkout the Core Data framework.
I m using tableview to populate an array from json file...In my view Controller i have tableview.when i run the project my table view codings are not executing.i dont know y?anyone help me pls.This is my viewcontroller file
#import "JSONparserViewController.h"
#implementation JSONparserViewController
#synthesize arraydata;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"No Of Elements in Array Data: %d",[arraydata count]);
return [arraydata count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 80;
}
// 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:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// Configure the cell...
NSLog(#"%#",arraydata);
NSDictionary *aTweet = [arraydata objectAtIndex:[indexPath row]];
cell.textLabel.text = [aTweet objectForKey:#"name"];
// NSDictionary *newArray=[aTweet objectForKey:#"properties"];
//
// NSDictionary *newArray1=[newArray objectForKey:#"propertyMeta"];
// cell.detailTextLabel.text = [newArray1 objectForKey:#"name"];
// cell.detailTextLabel.text = [newArray objectForKey:#"value"];
cell.textLabel.adjustsFontSizeToFitWidth = YES;
cell.textLabel.font = [UIFont systemFontOfSize:12];
cell.textLabel.minimumFontSize = 10;
cell.textLabel.numberOfLines = 4;
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
//cell.detailTextLabel.text = [newArray1 objectForKey:#"type"];
// NSURL *url = [NSURL URLWithString:[aTweet objectForKey:#"profile_image_url"]];
// NSData *data = [NSData dataWithContentsOfURL:url];
// cell.imageView.image = [UIImage imageWithData:data];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
NSLog(#"HIIIIIIIIII");
return cell;
}
Your Problem is you dont have any data in the arraydata object. Its count is zero. So Although you have set all delegate & datasource, Your table delegate methods will not called, because when it calls noofrowinSection, it returns zero.
Please verify that you have data in your arrayObject.
have you initialized your arraydata object...? and also it looks to me that you haven't set the delegate and datasource for your tableview becoz of which your nslog delegate methods are not being called.
Do this to set the delegate and datasource of tableView in your header file.
#interface JSONparserViewController: UIViewController<UITableViewDelegate,UITableViewDataSource>
{
}
Also check that your arraydata array is given memory or not.If not give it the memory first
you have nit allocate your array. firstly you have to allocate your Array wherever you assign your array value . NSLog your array in view will appear if printed then it must be executed
Please verify you have data in your array. And once after parsing is done, then reload the table in connectiondidfinishloading method. Table will be automatically reload.
I have a class that extends UITableviewController which displays a data type called "GigData" (which only contains strings for now). The content is stored in "data" which is an NSMutableArray containing NSMutableArrays containing "GigData". This array is passed to the instance of my class and the arrays inside arrays make up the sections of the table. Here is the code I have implemented so far:
#synthesize data = _data;
- (id)init
{
self = [super initWithStyle:UITableViewStyleGrouped];
_data = [[NSMutableArray alloc] init];
[[self navigationItem] setTitle:#"Gigs by Date"];
return self;
}
- (id)initWithStyle:(UITableViewStyle)style
{
return [self init];
}
- (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.
}
#pragma mark - View lifecycle
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [_data count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [[_data objectAtIndex:section] 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];
}
NSMutableArray *sectionArray = [_data objectAtIndex:[indexPath section]];
GigData *gig =[sectionArray objectAtIndex:[indexPath row]];
[[cell textLabel] setText:[gig description]];
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
GigData *temp = [[_data objectAtIndex:section] objectAtIndex:0];
return [temp date];
}
When I run the app, I can see everything sorted into the right groups and all the displays are correct, except for the final section, which keeps changing names, some of which have included "cs.lproj", "headers" and "method not allowed". Scrolling to the bottom of the table then towards the top crashes the app. Also, if I provide my own implementation for description for "GigData", the app crashes even worse, I cannot scroll to the second section at all. Data is declared as a property in the header file and is set to nonatomic and retain. I have also tried using the code inside the init method to create the data array inside this class, but this makes no difference. Some runnings of the app have said there is a problem in tableView:cellForRowAtIndexPath: when I create "sectionArray". Has any body got any suggestions as to what I am doing wrong?