My tableview crash when i scroll - xcode

I don't undestand... i succeed in populate my table view but when i scroll it crash without message..
i create my tabQuestion with a NSMutablearray and then add this in my delegate : cellForRowAtIndexPath
NSDictionary *question = [self.tabQuestion objectAtIndex:indexPath.row];
[cell setAccessoryType: UITableViewCellAccessoryDisclosureIndicator];
cell.textLabel.text = [NSString stringWithFormat:#"%#", [question objectForKey:#"question"]];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#", [question objectForKey:#"reponse"]];
if ([[question objectForKey:#"bOk"] isEqualToString:#"1"]) {
cell.imageView.image = [UIImage imageNamed:#"ok.png"];
}
else
{
cell.imageView.image = [UIImage imageNamed:#"ok.png"];
}
[question release];
return cell;

You shouldn't release objects that were returned by method objectAtIndex: of NSArray. It happens very rare.
Try to remove first of all line: [question release];
Then check if your self.tabQuestion contains needful amount of objects.

Related

XCode, table view cellForRowAtIndexPath

I know there is a simple solution to this but I can't seem to be able to tell :/
cell.textLabel.text = [BooksBorrowed objectAtIndex:0];
I have that in my cellForRowAtIndexPath method, bookName is a string.
It crashes and leaves no error in log. I dont know what I am doing wrong.
bookName is a string that i get from JSON Parsing and has content.
(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(#"Book Name is %#", BooksBorrowed[0]);
cell.textLabel.text = [BooksBorrowed objectAtIndex:0];
return cell;
}
This is how I get the BooksBorrowed array:
- (void)updateMyBooks
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Fetch data on a background thread:
NSString *authFormatString =
#"http://localhost:8888/Jineel_lib/bookBorrowed.php?uid=%d";
NSString *urlString = [NSString stringWithFormat:authFormatString, 1];
NSURL *url = [NSURL URLWithString:urlString];
NSString *contents = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
response1 = [contents JSONValue];
if (contents) {
NSMutableArray *newBooksBorrowed = [NSMutableArray array];
// ... Parse JSON response and add objects to newBooksBorrowed ...
BookName = [[NSString alloc]init];
DateBorrowed = [[NSString alloc]init];
BookID = [[NSString alloc]init];
BookExtended = [[NSString alloc]init];
BookReturned = [[NSString alloc]init];
BookName = [response1 valueForKey:#"BookName"];
BookID = [response1 valueForKey:#"BookID"];
DateBorrowed = [response1 valueForKey:#"DateBorrowed"];
BookExtended = [response1 valueForKey:#"Extended"];
BookReturned = [response1 valueForKey:#"Returned"];
NSLog(#"Book Name is %#", BookName);
[newBooksBorrowed addObject:BookName];
dispatch_sync(dispatch_get_main_queue(), ^{
// Update data source array and reload table view.
BooksBorrowed = newBooksBorrowed;
[self.tableView reloadData];
});
}
});
}
Are you sure bookName is a valid NSString? I would break at that line of code and type
po bookName
in the debugger to see if what you are assigning to bookName is in fact a valid NSString.
Oh, and make sure you returning a valid UITableViewCell at the end of that method, or else it is guaranteed your code will break.
Replace this code BooksBorrowed = newBooksBorrowed; with this in your function
BooksBorrowed = [[NSString alloc] initWithArray:newBooksBorrowed];
Hope it helps. Happy coding..
Thanks.
The solution to my questions was :
I had to change the part where I add my data into the table to :
NSString *string = [[NSString alloc] initWithFormat:#"%#",[BooksBorrowed objectAtIndex:indexPath.row]];
This is because a table view tends to not take things of element 0. Also I took out newBooksBorrowed and it works with just the BooksBorrowed array. :) Thank you everyone for helping me resolve it.

longpress custom items UICollectionViewCell image change

How can I make a cell imageview to change after longpress gesture?
With this one when I click on a cell (longpress) the 4 customized items appear but when I select one of them the app crashes. (if you remove :(Cell*)cell and cell.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:#"ICUbedRED.png"]]; it works...I mean the alertView appears but of course the image doesn't change).
- (void)longPress:(UILongPressGestureRecognizer *)recognizer {
if (recognizer.state == UIGestureRecognizerStateBegan) {
Cell *cell = (Cell *)recognizer.view;
[cell becomeFirstResponder];
UIMenuItem *highDep = [[UIMenuItem alloc] initWithTitle:#"High Dependency" action:#selector(hiDep:)];
UIMenuItem *lowDep = [[UIMenuItem alloc] initWithTitle:#"Low Dependency" action:#selector(lowDep:)];
UIMenuItem *booked = [[UIMenuItem alloc] initWithTitle:#"Booked" action:#selector(booked:)];
UIMenuItem *free = [[UIMenuItem alloc] initWithTitle:#"Free" action:#selector(free:)];
UIMenuController *menu = [UIMenuController sharedMenuController];
[menu setMenuItems:[NSArray arrayWithObjects:booked, highDep, lowDep, free, nil]];
[menu setTargetRect:cell.frame inView:cell.superview];
[menu setMenuVisible:YES animated:YES];
}
}
the voids are:
- (void)hiDep:(Cell*)cell
{
NSLog(#"Bed is HiDep");
cell.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:#"ICUbedRED.png"]];
UIAlertView *testAlert = [[UIAlertView alloc] initWithTitle:#"This Bed is High Dependency"
message:#""
delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[testAlert show];
[testAlert release];
}
- (void)lowDep:(Cell*)cell
{.
cell.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:#"ICUbedYELLOW.png"]];
..}
- (void)free:(Cell*)cell
{..
cell.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:#"ICUbedGREEN.png"]];
.}
- (void)booked:(Cell*)cell
{..
cell.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:#"ICUbedBLUE.png"]];
.}
and the cell building method is:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"Cell";
Cell *cvc = (Cell *)[collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
int i = indexPath.row%[labelArray count];
number = i;
UILongPressGestureRecognizer *recognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPress:)];
[cvc addGestureRecognizer:recognizer];
cvc.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:#"icubed.png"]];
cvc.label.text = [labelArray objectAtIndex:number];
return cvc;
}
#dottorfeelgood It is crashing for
cell.imageView.image = [UIImage imageNamed:[NSString stringWi......
because, the object retured as param to methods like
(void)lowDep:(Cell*)cell
is not of Class Cell, the retured param is of class UIMenuItem. because you are clicking on menuItems not Cell.
Instead of doing what you are doing now, you can use the MenuItems and corresponding actions on UICollectionCell solution provided by UICollectionView by default. You can check this tutorial here!
Just implement the 3 delegate methods and
// These methods provide support for copy/paste actions on cells.
// All three should be implemented if any are.
- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath;
- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender;
- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender;
and set your custom menuItems needed to the sharedMenuController in ViewdidLoad.
Hope this helps, excuse my bad sentence forming.

Xcode table view reload continually adds data to the table

I have an rss parser as part of my app code, and it is working fine and loading the rss xml file and populating the tableview fine.
The problem is with a refresh/reload button, which does reload the rss data, but it APPENDS the new data to the table and the table just grows and grows in size.
What the behaviour should do is to clear the old table data and rebuild the table with the new data - so that the table always shows just ONE set of data and doesn't keep growing every time the reload/refresh is pressed.
The table build code is as follows:
- (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] autorelease];
}
int storyIndex = [indexPath indexAtPosition: [indexPath length] - 1];
cell.textLabel.text = [[stories objectAtIndex: storyIndex] objectForKey: #"date"];
cell.detailTextLabel.text = [[stories objectAtIndex: storyIndex] objectForKey: #"title"];
[cell.textLabel setLineBreakMode:UILineBreakModeWordWrap];
[cell.textLabel setNumberOfLines:0];
[cell.textLabel sizeToFit];
[cell.detailTextLabel setLineBreakMode:UILineBreakModeWordWrap];
[cell.detailTextLabel setNumberOfLines:0];
[cell.detailTextLabel sizeToFit];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
And the reload/refresh button code is:
- (void)reloadRss {
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0, 0, 20, 20)];
UIBarButtonItem * barButton = [[UIBarButtonItem alloc] initWithCustomView:activityIndicator];
[[self navigationItem] setLeftBarButtonItem:barButton];
[barButton release];
[activityIndicator release];
[activityIndicator startAnimating];
[self performSelector:#selector(parseXMLFileAtURL) withObject:nil afterDelay:0];
[newsTable reloadData];
}
I have tried to solve this by adding the line:
if (stories) { [stories removeAllObjects]; }
to the reload section, which I think should work and does clear the table, but the app then crashes the app with an EXC_BAD_ACCESS.
Any ideas or suggestions greatly appreciated!
Actually, have now solved this!
Was due to "autoreleasing" elements of the array, so after clearing this out, they were invalid.
Removing autorelease and just releasing these objects in the final dealloc worked.
The Code EXC_BAD_ACCESS does mean, that you want connect at a variable that does not exists anymore.
In your code example, I can see, the problem to see at the following two lines of code:
[activityIndicator release];
[activityIndicator startAnimating];
You release the activityIdicator befor starting the Animating.
Try to release at the end of the function.
[activityIndicator startAnimating];
[self performSelector:#selector(parseXMLFileAtURL) withObject:nil afterDelay:0];
[newsTable reloadData];
[activityIndicator release];

SDWebImage and UITableViewCell

I'm working with SDWebImage and UITableView
- (UITableViewCell *)tableView:(UITableView *)the_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *MyIdentifier = [NSString stringWithFormat:#"MyIdentifier"];
NSDictionary *info = [tableData objectAtIndex:indexPath.row];
UITableViewCell *cell = [the_tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:MyIdentifier] autorelease];
if(!addImage) [addImage release];
addImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"placeholder.png"]];
[addImage setFrame:CGRectMake(7, 10, 50, 50)];
[cell setIndentationLevel:6];
[cell.contentView addSubview:addImage];
}
if(info != NULL) {
cell.textLabel.text = [info objectForKey:#"title"];
cell.detailTextLabel.text = [NSString stringWithFormat:#"Version: %#",[info objectForKey:#"version"]];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
NSString *imageURL = [NSString stringWithFormat:#"%#",[info objectForKey:#"imageURL"]];
[addImage setImageWithURL:[NSURL URLWithString:imageURL] placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
}
return cell;
}
Which Works Great for the first 6 Results (The amount that can fit on the immediate view)
But as I scroll down the list, it seems like it's just re-using images from the first 6 cells, and on some cells images change depending on their location on the screen.
Also, if I call reloadData, the images from the previous UITableCells stay on screen!
Am I doing something wrong here? I've followed the example code on github..
Thanks!
(Answered by the OP in a question edit. Moved here as a community wiki answer. See Question with no answers, but issue solved in the comments (or extended in chat) )
The OP wrote:
OK, So I found the problem.
For anyone else out there with the Same issue, this is where you're doing it wrong!
Notice how I'm adding the Image into SubView while creating a cell:
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:MyIdentifier] autorelease];
addImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"placeholder.png"]];
[addImage setFrame:CGRectMake(7, 10, 50, 50)];
[cell.contentView addSubview:addImage];
Well, what SDWebImage was trying to do is constantly update that addImage variable, which wasn't a property of my cell class.
So, what I did to fix this problem is create my own UITableViewCell subclass, that init's with a ImageView and I get SDWebImage to setImage on that property!
I hope this helps someone!

iPhone UITableViewCell slow performance

I just wrote a small application that read from a site feed and display in UITableViewCell. I am using custom view cell and my UITableView is screwed in scrolling like it is not very smooth in scrolling upside down. Any idea? Here's the code for my UITableViewCell,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CustomCell";
CustomCell *cell = (CustomCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
// cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:nil options:nil];
for(id currentObject in topLevelObjects) {
if([currentObject isKindOfClass:[UITableViewCell class]]) {
cell = (CustomCell *) currentObject;
break;
}
}
}
//MiceAppDelegate *AppDelegate = (MiceAppDelegate *)[[UIApplication sharedApplication] delegate];
if(dataArray != nil) {
//
//NSArray *promoArray = (NSArray *) promotions;
NSDictionary *datadict = [self.dataArray objectAtIndex:indexPath.row];
NSString *url = [datadict objectForKey:#"imageUrl"];
NSString *title = [datadict objectForKey:#"title"];
NSString *description = [datadict objectForKey:#"description"];
NSString *newAddressPartOfURL = [url stringByReplacingOccurrencesOfString:#" " withString:#"+"];
//NSLog([url stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]);
NSURLResponse *urlResponse;
NSData *data = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:newAddressPartOfURL]] returningResponse:&urlResponse error:nil];
// Configure the cell.
UIImage *urlImage = [[UIImage alloc] initWithData:data];
// NSLog(#"%i",[imageView.image topCapHeight]);
cell.title.text = title;
cell.description.text = description;
cell.image.image = urlImage;
[urlImage release];
}
return cell;
}
Doing synchronous downloads as your cells are being drawn is definitely going to cause some unsmooth scrolling. You could try to replace those with asynchronous calls, and filling in the data with a generic object while the download is happening. When the download completes, then call reloadData on your tableview.
afaik the dequeueReusableCellWithIdentifier method is called as cells get flush etc. Build your data / do the requests on init, not in the cell creation!

Resources