In UITableview array shows null thread SIGABRT error - iphone

I am new to iOS development. I am developing my project which is fully based on XML parsing from url. I parsed XML data and stored in an array but I am not able to display the arraydata in UITableView.
Here is my code.
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
eventarray = [[NSMutableArray alloc]init];
xmlParserObject = [[NSXMLParser alloc] initWithData:webData];
[xmlParserObject setDelegate:self];
[xmlParserObject parse];
for (int i =0; i<[rssOutputData count]; i++) {
Eventlist *log = [rssOutputData objectAtIndex:i];
eventid = log.id;
NSLog(#"%d",eventid);
Invit = log.eventname;
NSLog(#"%#",Invit);
}
[rssOutputData release];
[connection release];
[tblView reloadData];
}
My array prints the value here, but how to pass this array data in UITableView. I tried this but I didn't get data in table view.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"eventCell";
UITableViewCell *cell= [[tableViewdequeueReusableCellWithIdentifier:CellIdentifier]autorelease];
if(indexPath.section == 0)
{
Eventlist *msglist = [eventarray objectAtIndex:indexPath.row];
cell.textLabel.text = msglist.eventname;
cell.textLabel.textColor = [UIColor greenColor];
}
if(indexPath.section == 1)
{
UIButton *viewmoreButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
viewmoreButton.frame = CGRectMake(200.0f, 5.0f, 75.0f, 30.0f);
[viewmoreButton setTitle:#"View More" forState:UIControlStateNormal];
[cell addSubview:viewmoreButton];
[viewmoreButton addTarget:self action:#selector(viewMore:)forControlEvents:UIControlEventTouchUpInside];
}
return cell;
}
Appreciate your help.

Thats not the proper way to load the data in tableView(when parsing xml).Because you're completly not sure whether you will get the data immediately you parse it(for the big xml files).
Implement NSXMLParser's delegate method called,
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
//here your [tableView reloadData] goes...
}
Sent by the parser object to the delegate when it has successfully completed parsing.

it looks like you are storing your data in rssOutputData, but you are calling [rssOutputData release]; at the end of connectionDidFinishLoading. You are probably throwing out your data there.
It looks like eventArray never has anything added to it. That will cause a crash if you try to access an index that doesn't exist.
try changing your for loop to:
for (int i =0; i<[rssOutputData count]; i++) {
Eventlist *log = [rssOutputData objectAtIndex:i];
eventid = log.id;
NSLog(#"%d",eventid);
Invit = log.eventname;
NSLog(#"%#",Invit);
[eventArray addObject:log];
}

As much as i understand your code, i didn't see you populating your eventarray because in cellForRowAtIndexPath you are fetching some record from that array and trying to display values in cell so definitly it would be empty at that time.

Please follow this link for create sample tableview.replace the array data instead of constant data with your response data array.After getting your array values use [tableview reloadData];

Related

reload tableview after call to WCF service

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.

Xcode TableView showing to different arrays one at a time PROBLEM

So I know that if you guys don't like my question you are going to vote me down and reduce my reputation :( but I need to learn and can't find a answer so here I'm risking my reputation again.
Now to the point. All I'm trying to do is one View with two buttons and a table view under the buttons, this table view needs to display a different array depending witch button was click, in other words all I want it to do is if I click button1 display array1, if I click button2 display array2, simple! but I can't get it to work.
Here is a sample of my code:
- (void)viewDidLoad
{
array1 = [[NSArray arrayWithObjects:
#"A",
#"B",
#"c",
#"D", nil] retain];
array2 = [[NSArray arrayWithObjects:
#"1",
#"2",
#"3",
#"4", nil] retain];
}
- (IBAction)btnPeriodicos:(id)sender {
displayArray = 1;
}
- (IBAction)btnRadios:(id)sender {
displayArray = 2;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (displayArray == 1) {
return [array1 count];
}
if (displayArray == 2) {
return [array2 count];
}
[self.tableView reloadData];
}
- (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.textAlignment = UITextAlignmentCenter;
cell.textLabel.textColor = [UIColor blackColor];
if (menuNumberInt == 1) {
cell.textLabel.text = [[periodicoArray objectAtIndex:indexPath.row] retain];
}
if (menuNumberInt == 2) {
cell.textLabel.text = [[radioArray objectAtIndex:indexPath.row] retain];
}
return cell;
}
If I put instead of the if else statements either [array1 count] for the numberOfRowsInSection and the cell.textLabel.text = [[periodicoArray objectAtIndex:indexPath.row] retain]; the app loads with the table fill with that array so I guess the table works, but how can I make my buttons change the table cells?
any help is greatly appreciated.
Thanks
You can have an iVar variable for NSArray *currentArray. In viewDidLoad you can define your two arrays (as you currently do) but then assign currentArray to array1.
Then, change all the tableView callbacks to operate off of currentArray and get rid of the if (displayArray == x) checks.
in the (IBAction) button handlers, assign currentArray to the appropriate array and call [tableView reloadData]. that will clear the table and trigger all the tableView callbacks to happen again. since the currentArray changed, all the callback will pull data from the appropriate array.
Hope that helps.

Problem with IndexPath.row

i have 60 rows in an table view.i have an array named as "BundleImagesArray " with 60 bundle images names.So i am retrieving the images from bundle and creating thumbnail to it.
whenever binding each cell at first time ,i am storing the Thumbnail images in to an array.because of enabling the fast scrolling after bind each cell.i am utilizing the images from the array(without creating the thumbnail again).however the imageCollection array(which will store thumbnail images) is disorder some times
the Index path.row is coming as 1,2.....33,34,50,51..etc
its not an sequential order.so i am getting trouble with my imageCollection array which is used to store and retrieve images according to the index path.may i know what is the reason for that.can any one provide me a good solution for this.is there any way to get the indexpath.row as sequential order?
my cellForRowAtIndexPath code is:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"IndexPath Row%d",indexPath.row);
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
if ([cell.contentView subviews])
{
for (UIView *subview in [cell.contentView subviews])
{
[subview removeFromSuperview];
}
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
[cell setAccessoryType:UITableViewCellAccessoryNone];
Class *temp = [BundleImagesArray objectAtIndex:indexPath.row];
UIImageView *importMediaSaveImage=[[[UIImageView alloc] init] autorelease];
importMediaSaveImage.frame=CGRectMake(0, 0, 200,135 );
importMediaSaveImage.tag=indexPath.row+1;
[cell.contentView addSubview:importMediaSaveImage];
UILabel *sceneLabel=[[[UILabel alloc] initWithFrame:CGRectMake(220,0,200,135)] autorelease];
sceneLabel.font = [UIFont boldSystemFontOfSize:16.0];
sceneLabel.textColor=[UIColor blackColor];
[cell.contentView addSubview:sceneLabel];
//for fast scrolling
if([imageCollectionArrays count] >indexPath.row){
importMediaSaveImage.image =[imageCollectionArrays ObjectAtIndex:indexPath,row];
}
else {
//for start activity indicator
[NSThread detachNewThreadSelector:#selector(showallstartActivityBundle) toTarget:self withObject:nil];
NSData *datas = [self photolibImageThumbNailData:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:temp.fileName ofType:#"png" inDirectory:#"Images"]]];
importMediaSaveImage.image =[UIImage imageWithData:datas];
[imageCollectionArrays addObject:importMediaSaveImage.image];
//to stop activity indicator
[NSThread detachNewThreadSelector:#selector(showallstopActivityBundle) toTarget:self withObject:nil];
}
sceneLabel.text = temp.sceneLabel;
temp = nil;
return cell;
}
Getting the tableview to call you in a particular order is not the right solution. You need to be able to provide any cell it needs in any order.
I think the problem is that you are using an array and trying to access indexes that don't exist yet. You could use an NSMutableDictionary for your imageCollectionArrays (instead of NSArray) and store your data there, keyed by row (or NSIndexPath). They you can add or retrieve them in any order.
An NSArray is perfectly fine for UITableView rows. The rows are ordered, and an array is also ordered, so no problem there.
The problem in your code seems to be that you are using two arrays, one immutable and one mutable. You are adding objects to the mutable array, and so it is not exactly predictable where they will be added (because it is not predictable that the rows are going to be needed in order).
I recommend filling your NSMutableArray first with [NSNull null] objects, and then inserting the image at a specific point in the array:
// during initialization
for (int i=0; i<numberOfImages; i++) {
[imageCollectionArrays addObject:[NSNull null]];
}
// in cellForRowAtIndexPath:
[imageCollectionArrays replaceObjectAtIndex:indexPath.row
withObject:importMediaSaveImage.image];
Try that, see if it works.

uitableview cellforrowatindexpath not called but no:of rows in section is called

in my tableview no of rows in section method is called and it returns value 17,but the cellforrowatindexpath is not getting called.i have put breakpoints in the first line of this method but this point is never shown when debugging,i have followed the tableviewdelegate and datasource.and the tableviews datasource,delegate are properly set in the Int builder.
i am also posting some of the code
in my viewcontroller.m
-(void)viewDidLoad
{
tweets=[[NSMutableArray alloc]init];
[self updateStream:nil];
[self.tweetsTable setDelegate:self];
[self.tweetsTable setDataSource:self];
}
-(NSInteger)tableView:(UITableView *)tweetsTable numberOfRowsInSection:(NSInteger)section {
return [tweets count];
}
-(UITableViewCell *)tableView:(UITableView *)tweetsTable cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"twitCell";
TwitCell *cell = (TwitCell *)[tweetsTable dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = (TwitCell *)[[[TwitCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.tweet = [tweets objectAtIndex:indexPath.row];
[cell layoutSubviews];
return cell;
}
cellForRowAtIndexPath won't get called if your tableview has height of 0
make sure your tableview always has VISIBLE rows
CGRect frame = self.tableView.frame;
frame.size.height = 100;
self.table.frame = frame;
It will not get called if you are returning 0 rows in numberOfRowsInSection method.
Please check the number of rows that you return.
Given the code you've shown us there only a few possibilities. Either self.tweetsTable is nil, tweets is nil, or tweets contains no element and count is returning zero. Now I know you say that everything is correct, but clearly something is up! You can add a bit of defensive code to detect these problems.
-(void)viewDidLoad
{
tweets=[[NSMutableArray alloc]init];
[self updateStream:nil];
NSAssert(self.tweetsTable, #"self.tweetsTable must not be nil.");
[self.tweetsTable setDelegate:self];
[self.tweetsTable setDataSource:self];
}
-(NSInteger)tableView:(UITableView *)tweetsTable numberOfRowsInSection:(NSInteger)section {
NSAssert(tweets, #"tweets must not be nil here");
NSUInteger n = [tweets count];
if(n == 0)
NSLog(#"WARNING: %# returning 0", __PRETTY_FUNCTION__);
return (NSInteger)n;
}
If you do this and one of the asserts fires you'll know where your problem is. If no assert fires then something is going on outside the scope of the code you have shown (e.g. something is getter released to soon or memory getting clobbered). Oh and one final thing -- can you see the empty table view on the screen? If you table is not visible AFAIK cellForRowAtIndexPath won't be called.
check this
or else use viewDidLoad code in viewWillAppear
Here is my function. After I placed "dispatch_async(dispatch_get_main_queue()..." inside of "tweets = [NSJSONSerialization.....", it works.
tweets = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableLeaves error:&jsonError];
if (tweets) {
// We have an object that we can parse
NSLog(#"%#", tweets);
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
else {
// Inspect the contents of jsonError
NSLog(#"%#", jsonError);
}
In my cases I had created a UITableView as a property on my view controller, but I forgot to add it as a subview to self.view
Strangely you will get the symptoms that sujith described: numberOfRowsInSection will be called, but cellForRowAtIndexPath will not!
This was my missing line:
[self.view addSubView:self.myTableViewProperty];
And to defend against it:
NSAssert(self.myTableViewProperty.superview != nil, #"The table view dose not have a superview");
[self.myTableViewProperty reloadData];
You can refer following code to reload your tableView
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
In my case I was using custom subclass of UITableView and I have not called super super.layoutSubviews()
override func layoutSubviews() {
super.layoutSubviews() // Forgotten to call super implementation
self.layer.borderColor = Constants.primaryColor.cgColor
self.layer.borderWidth = Constants.primaryBorderWidth
self.indicatorStyle = .white
}

Cant bind data to a table view

I have retrieved data from Json URL and displayed it in a table view. I have also inlcuced a button in table view. On clicking the button the data must be transferred to a another table view. The problem is that i could send the data to a view and could display it on a label. But i couldnt bind the dat to table view ... Here's some of the code snippets...
Buy Button...
-(IBAction)Buybutton{
Product *selectedProduct = [[data products]objectAtIndex:0];
CartViewController *cartviewcontroller = [[[CartViewController alloc] initWithNibName:#"CartViewController" bundle:nil]autorelease];
cartviewcontroller.product= selectedProduct;
[self.view addSubview:cartviewcontroller.view];
}
CartView...
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
data = [GlobalData SharedData];
NSMutableArray *prod =[[NSMutableArray alloc]init];
prod = [data products];
for(NSDictionary *product in prod){
Cart *myprod = [[Cart alloc]init];
myprod.Description = [product Description];
myprod.ProductImage =[product ProductImage];
myprod.ProductName = [product ProductName];
myprod.SalePrice = [product SalePrice];
[data.carts addObject:myprod];
[myprod release];
}
Cart *cart = [[data carts]objectAtIndex:0];
NSString *productname=[cart ProductName];
self.label.text =productname;
NSLog(#"carts");
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [data.carts count];
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 75;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"cellforrow");
static NSString *CellIdentifier = #"Cell";
ProductCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell ==nil)
{
cell = [[[ProductCell alloc]initWithFrame:CGRectZero reuseIdentifier:CellIdentifier]autorelease];
}
NSUInteger row = [indexPath row];
Cart *cart = [[data carts]objectAtIndex:row];
cell.productNameLabel.text = [cart ProductName];
return cell;
}
I am also getting the following error in the console
2010-06-11 18:34:29.169 navigation[4109:207] *** -[CartViewController tableView:numberOfRowsInSection:]: message sent to deallocated instance 0xcb4d4f90
Your view controller is autoreleased that's why you have the error in the console.
CartViewController *cartviewcontroller =
[[[CartViewController alloc]
initWithNibName:#"CartViewController"
bundle:nil] ***autorelease***];
You should store your view controller in a member variable.
This is depreciated:
cell = [[[ProductCell alloc]initWithFrame:CGRectZero reuseIdentifier:CellIdentifier]autorelease];
Use initWithStyle:reuseIdentifier: instead.
Autorelease isn't a convenience function. It has a specific use. You're only supposed to use it when you are immediately handing an object off to an another external object. Don't use autorelease unless the sending object longer cares if the receiving object lives or dies.
A good rule of thumb is if you ever refer to the receiving object again in the sending object, don't autorelease the receiving object.