Some table cells are not displaying - ios

I ran into a problem at my app today. I have a table inside a View Controller. The problem happens when I tap the Compare button. When I tap the compare button, a small animation occurs, every cell is resized to allow a selected or not selected image to appear.
Here is a video with the problem: https://www.youtube.com/watch?v=6SkIbp1xf0E
The problem is that, while all cels should have the default not selected button, some cells don't get the image displayed.
Here is a chuck of my code.
//animate function
-(void)animate{
[[tableView visibleCells] enumerateObjectsUsingBlock:^(CustomCell *cell, NSUInteger idx, BOOL *stop)
{
[cell.myImageView setFrame:CGRectMake(cell.frame.size.width * 0.15 +
cell.myImageView.frame.origin.x, cell.myImageView.frame.origin.y +
cell.frame.size.height * 0.1, cell.myImageView.frame.size.width * 1.25,
cell.myImageView.frame.size.height * 1.25)];
completion:^(BOOL finished)
{
// code to execute when the animation finishes
[UIImageView animateWithDuration:1 animations:^{
//select button animation
cell.compareProduct.image = [UIImage imageNamed:#"deselectedProduct.png"];
cell.compareProduct.hidden = false;
[cell.compareProduct setAlpha:0];
[UIImageView beginAnimations:NULL context:nil];
[UIImageView setAnimationDuration:1.0];
[cell.compareProduct setAlpha:1];
[UIImageView commitAnimations];
}];}
}
This chunk of code executes everytime flawlessly. Every cell in I see display the selected \ not selected button. The problem happens when I scroll.
-(void)tableView:(UITableView *)theTableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
if (compareActive) //if compare button was pressed
{
[[tableView visibleCells] enumerateObjectsUsingBlock:^(CustomCell *cell, NSUInteger idx, BOOL *stop) {
CGRect someRect = CGRectMake(cell.frame.size.width * 0.15 +
cell.myImageView.frame.origin.x, cell.myImageView.frame.origin.y +
cell.frame.size.height * 0.1, cell.myImageView.frame.size.width * 1.25,
cell.myImageView.frame.size.height * 1.25);
[cell.myImageView setFrame:someRect];
// i was forced to place another moving animation so the user won't notice how the image jumps from the old frame to the new frame
[cell setFrame:CGRectMake(cell.frame.size.width, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)];
[UIView animateWithDuration:1 animations:^{
[cell setFrame:CGRectMake(0, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)];
}];}
}
Why some cells don't have the selected not selected displayed and why the frame jumps? Also, don't forget I am using a CustomCell.
If you have a better solution or other functions to use please point me to them. The feature I want is this: I press the compare button, all table cells change their frames at one time.
Thanks in advance.

I think [tableView visibleCells] and willDisplayCell: functions aren't a good match.
It's possible that the cell firing willDisplayCell: is not returned immediately after when you call [tableView visibleCells].
I guess you should use a bool variable in your ViewController and look at it while reloading your Table View via cellForViewAtIndexPath:. And then call reloadData when the user clics on your Compare button.

Related

Bounce Animation on UITableViewCell

When the UITableView loads I want its first cell to bounce from the Right side, so It indicates the User that they can swipe right to delete a cell.
How can I do this ?
My code so far:
note: In the following code I am just making the cell to blink, but what I actually want is the cell to bounce.
-(void) tableView:(UITableView *) tableView willDisplayCell:(UITableViewCell *) cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
//row number on which you want to animate your view
//row number could be either 0 or 1 as you are creating two cells
//suppose you want to animate view on cell at 0 index
if(indexPath.row == 0) //check for the 0th index cell
{
// access the view which you want to animate from it's tag
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:1];
UIView *myView = [self.tableView cellForRowAtIndexPath:indexPath];
NSLog(#"row %ld",(long)indexPath.row);
// apply animation on the accessed view
[UIView animateWithDuration:5
delay:2
options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat | UIViewAnimationOptionCurveEaseInOut animations:^
{
[myView setAlpha:0.0];
} completion:^(BOOL finished)
{
[myView setAlpha:1.0];
}];
}
}
If I understand this correctly, you wish to bounce the cell from left to right?
Get a reference to the cell's contentView:
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:1];
UIView *contentView = [self.tableView cellForRowAtIndexPath:indexPath].contentView;
Now there are many ways to 'bounce' this contentView. One way would be to use an animation block like this:
CGRect original = contentView.frame;
CGRect bounce_offset = original;
original.origin.x -= 100.0f;
What we do here, is remember the original frame, and decide how far we want our bounce to reach in the animation block. Then we can animate for example doing something like this:
[UIView animateWithDuration:0.5f delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
contentView.frame = bounce_offset;
} completion:^(BOOL finished) {
[UIView animateWithDuration:1.0f delay:0.0f usingSpringWithDamping:0.75f initialSpringVelocity:0.0f options:UIViewAnimationOptionCurveEaseOut animations:^{
contentView.frame = original;
} completion:^(BOOL finished) {
}];
}]
You could also use autoreverse options, this 'a' way to do it though. Let me know what your thoughts are!

iOS Textfield / select combo to filter through large set of data

I'm fairly new to iOS programming so please excuse anything idiotic that will precede :)
I have a form, where one of the fields can only be a certain predefined value. The list has over 500 options.
I have implemented the use of Search Bar and Display controller in Storyboard and have parsed the data into NSArray for it to be filtered.
Issue I had was the appearance. So what I've done is applied another View (only View that is in storyboard - not sure if this is correct?) and have placed the TableView and Search box into the view). This way I can show / hide the view.
I then created a button (which will look like a field - if that makes sense) where I've applied action to it to show the view.
I can show the view and search / select a cell (which is subsequently updating the button value)
Issue is, after I've selected a option, I can't do this again, i.e. no further click (IBAction) are coming through. Here's my code:
- (IBAction)selectionClick:(id)sender
{
[UIView animateWithDuration:0.25 animations:^{
_searchView.alpha = 1.0f;
} completion:^(BOOL finished) {
[_searchView setHidden:NO];
}];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellText = cell.textLabel.text;
[_SelectionValue setTitle:cellText forState:UIControlStateNormal];
[self.view endEditing:YES];
tableView.hidden = YES;
[UIView animateWithDuration:0.25 animations:^{
_SearchView.alpha = 0.0f;
} completion:^(BOOL finished) {
[_SearchView setHidden:YES];
}];
}
}
If you need any further info please let me know :)
Setting to 0 alpha and hiding the view doesn't remove the view from the view controller. The view is still present but invisible and block any actions to the view behind hit.
Try
[_SearchView removeFromSuperview];
Instead of
[UIView animateWithDuration:0.25 animations:^{
_SearchView.alpha = 0.0f;
} completion:^(BOOL finished) {
[_SearchView setHidden:YES];
}];
also
variable names normally start lowercased letter. Most examples follow this format.

animating UITableViewHeader to grow/shrink

Im very new to iOS and am trying to figure out how I can animate the tableView header to appear like its sliding down from the top of the view, stay there for 3 seconds, then slide back up and disappear.
I havent done any animation of any kind before so I could really use some help. I dont know where to start. Ive looked at other answers on here but cant seem to figure out how to do it.
ive got my table view appearing just fine with this code in my viewDidLoad of my UITableViewController class
self.headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320,15)];
self.headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 15)];
self.headerLabel.textAlignment = NSTextAlignmentCenter;
self.headerLabel.text = #"some text";
[self.headerView addSubview:self.headerLabel];
self.tableView.tableHeaderView = self.headerView;
self.tableView.tableHeaderView.frame = CGRectMake(0, 0, 320, 15);
I assume I need to animate the height of my frame.
edit: I found this code which seems like it should work, however it crashes my app when the animation runs
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[UIView animateWithDuration:3.0f
delay:0.0f
options: UIViewAnimationOptionBeginFromCurrentState
animations:^{
self.headerView.frame = CGRectMake(0.0f, 0.0f, 320.f, 0.0f);
}
completion:^(BOOL finished) {
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}];
}
I don't know if you can animate a table view's header view like you want to. With a complex UI object like a Table view Apple tends to treat the views that make up the object as private, and bad things tend to happen when you try to manipulate the view hierarch.
If you're not using auto-layout and you want to animate another view that is part of YOUR view hierarchy then your code might be as simple as something like this:
CGPoint center = myView.center;
CGFloat myViewBottom = myView.frame.origin.y + myView.frame.origin.size.height;
//Move the view above the top of it's superview before starting the animation.
center.y -= myViewBottom;
//Animate the view down into position
[UIView animateWithDuration: .2
animations:
^{
myView.center += myViewBottom;
};
completion:
^{
//As the completion block for the first animation, trigger another
//animation to animate the view away again. This time delay
//for 3 second before the 2nd animation.
[UIView animateWithDuration: .2
delay: 3.0
options: 0
animations:
^{
myView.center -= myViewBottom;
};
completion: nil
}
];
Try to use beginUpdates and endUpdates, here is an example:
in your header
#property NSInteger newOffset;
implementation:
- (void) colapseHeader
{
_newOffset = 50;
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 50 + _newOffset;
}
- (void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
_newOffset = 100;
[self.tableView beginUpdates];
[self.tableView endUpdates];
[self performSelector:#selector(colapseHeader) withObject:nil afterDelay:3];
}

Animation of UILabel's frame (and other views' frames) in UITableViewCell

Please help. Trying to get animation of frame position working inside a UITableViewCell, specifically I'm trying to move the default UILabel (cell.textLabel). However, no matter what technique I use, I can't get any view inside the cell to move. The animation of colour and alpha works as outlined by the code below.
Cheers in advance for help.
Andy
Here is the code I am using:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0 && indexPath.row == 0) {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
CGRect textLabelFrame = cell.textLabel.frame;
textLabelFrame.origin.x = -textLabelFrame.size.width;
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationCurveEaseOut
animations:^{
cell.textLabel.frame = textLabelFrame; // THIS DOESN'T WORK - HELP!
cell.imageView.frame = CGRectOffset(cell.imageView.frame,0,0); // EVEN TRYING TO MOVE IMAGEVIEW DOESN'T WORK
cell.textLabel.alpha = 0; // This animates
cell.imageView.backgroundColor = [UIColor redColor]; // This animates
}
completion:^(BOOL finished){
NSLog(#"Done!");
}];
}
}
I don't think it's possible to reposition the default label or image view in a standard cell. If you want to do that, you should add your own subviews to the cell's contentView, and do your animations with those.

Click on tablecell show UIDatePicker

I have a tableview controller and one of the cell is "date" and when i click i wanna show a datepicker and update the values.
When i click on limit date i get
Now here is the code:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ( indexPath.section == 0 )
{
if ( indexPath.row == 3 )
{
UITableViewCell *targetCell = [tableView cellForRowAtIndexPath:indexPath];
self.pickerView.date = [self.dateFormatter dateFromString:targetCell.detailTextLabel.text];
// check if our date picker is already on screen
if (self.pickerView.superview == nil)
{
[self.view.window addSubview: self.pickerView];
// size up the picker view to our screen and compute the start/end frame origin for our slide up animation
//
// compute the start frame
CGRect screenRect = [[UIScreen mainScreen] applicationFrame];
CGSize pickerSize = [self.pickerView sizeThatFits:CGSizeZero];
CGRect startRect = CGRectMake(0.0,
screenRect.origin.y + screenRect.size.height,
pickerSize.width, pickerSize.height);
self.pickerView.frame = startRect;
// compute the end frame
CGRect pickerRect = CGRectMake(0.0,
screenRect.origin.y + screenRect.size.height - pickerSize.height,
pickerSize.width,
pickerSize.height);
// start the slide up animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
// we need to perform some post operations after the animation is complete
[UIView setAnimationDelegate:self];
self.pickerView.frame = pickerRect;
// shrink the table vertical size to make room for the date picker
CGRect newFrame = self.tableView.frame;
newFrame.size.height -= self.pickerView.frame.size.height;
self.tableView.frame = newFrame;
[UIView commitAnimations];
// add the "Done" button to the nav bar
self.navigationItem.rightBarButtonItem = self.doneButton;
}
}
}
}
- (IBAction)dateChanged:(id)sender
{
[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:3 inSection:0]].detailTextLabel.text = [self.dateFormatter stringFromDate:[sender date]];
}
- (void)slideDownDidStop
{
[self.pickerView removeFromSuperview];
}
- (IBAction)doneAction:(id)sender
{
CGRect screenRect = [[UIScreen mainScreen] applicationFrame];
CGRect endFrame = self.pickerView.frame;
endFrame.origin.y = screenRect.origin.y + screenRect.size.height;
// start the slide down animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
// we need to perform some post operations after the animation is complete
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(slideDownDidStop)];
self.pickerView.frame = endFrame;
[UIView commitAnimations];
// grow the table back again in vertical size to make room for the date picker
CGRect newFrame = self.tableView.frame;
newFrame.size.height += self.pickerView.frame.size.height;
self.tableView.frame = newFrame;
// remove the "Done" button in the nav bar
self.navigationItem.rightBarButtonItem = nil;
// deselect the current table row
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
self.navigationItem.rightBarButtonItem = self.nextButton;
}
I have three questions:
First: what is that black bar on top of datepicker and how do i remove it?
Second: what can i do for closing the datepicker when the user clicks outside the datepicker?
Third: How can i move the tableview scroll so that the field "limit date" can be visible when datepicker opens?
Sorry for the big screenshots.
What about presenting your date picker modally in UIActionSheet?
In the example above that black bar (which is probably a sizing issue) is replaced with a convenient toolbar in which you can place buttons like "save" and "cancel", and I believe that if you use a UIActionSheet and click outside of it it's automatically dismissed (I'm not sure about this), but if' it's not you can use it's dismiss method to hide it.
About the table view, you can use [myTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:someRow inSection:someSection] atScrollPosition:UITableViewScrollPositionMiddle animated:YES]; to set the offset of the table scroll at a particular cell you want.

Resources