CollectionView Should scroll to last cell - objective-c

I am using collection view to showing the taken images of my app.I want as soon as the image taken the collection view should automatically move to last object in my collection view .My collection scrolls horizontally
Please help me to do this.
I have searched in google and i have found i have applied this code in my project
i have applied this code in my project in viewwillappear ,it showing error,
Please help me to do this
click here to see i am taking photo and showing in below ,ok ,in this image it has 3pictures ,if i again take a picture 4th picture will be there in collection view ,if user want to se the 4th picture means ,user want scroll by manually and can see it...
Here is my code:
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[self navigationController] setNavigationBarHidden:NO animated:YES];
[session startRunning];
NSInteger section = [self numberOfSectionsInCollectionView:self.collection_View] - 1;
NSInteger item = [self collectionView:self.collection_View numberOfItemsInSection:section] - 1;
NSIndexPath *lastIndexPath = [NSIndexPath indexPathForItem:item inSection:section];
}
I want automatically scroll to the last pictures in horizontally
Thanks in Advance !!!

Add the following line inside your viewWillAppear method code:
[collectionView scrollToItemAtIndexPath:lastIndexPath atScrollPosition:UICollectionViewScrollPositionBottom animated:YES];
Use this:
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[self navigationController] setNavigationBarHidden:NO animated:YES];
[session startRunning];
NSInteger section = [self numberOfSectionsInCollectionView:self.collection_View] - 1;
NSInteger item = [self collectionView:self.collection_View numberOfItemsInSection:section] - 1;
NSIndexPath *lastIndexPath = [NSIndexPath indexPathForItem:item inSection:section];
[collectionView scrollToItemAtIndexPath:lastIndexPath atScrollPosition:UICollectionViewScrollPositionBottom animated:YES];
}

Here's the Swift 4.2 version of the accepted answer
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let section = numberOfSections(in: collectionView) - 1
let item = collectionView.numberOfItems(inSection: section) - 1
let lastIndexPath = IndexPath(item: item, section: section)
collectionView.scrollToItem(at: lastIndexPath, at: .bottom, animated: true)
}

Related

iOS Simulator Not Recognizing Gestures

I am adding a UISwipeGestureRecognizer and a UITapGestureRecognizer to a view in a view controller's viewDidLoad method.
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addGestureRecognizer:[[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(cardSwipe:)]];
[self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(cardTap:)]];
}
- (void)cardSwipe:(UISwipeGestureRecognizer *)sender {
//get the card. set faceUp to false.
CGPoint location = [sender locationInView:sender.view];
NSIndexPath *cellIndex = [self.cardCollectionView indexPathForItemAtPoint:location];
if(cellIndex){
UICollectionViewCell *cell = [self collectionView:self.cardCollectionView cellForItemAtIndexPath:cellIndex];
if(cell && [cell isKindOfClass:[CardCollectionViewCell class]]){
[[((CardCollectionViewCell *)cell) cardView] handleCardSwipe];
}
}
}
- (void)cardTap:(UITapGestureRecognizer *)sender {
//get the card. set faceUp to false.
CGPoint location = [sender locationInView:sender.view];
NSIndexPath *cellIndex = [self.cardCollectionView indexPathForItemAtPoint:location];
if(cellIndex){
UICollectionViewCell *cell = [self collectionView:self.cardCollectionView cellForItemAtIndexPath:cellIndex];
if(cell && [cell isKindOfClass:[CardCollectionViewCell class]]){
[[((CardCollectionViewCell *)cell) cardView] handleCardSwipe];
}
}
}
In case this is relevant: The view contains a UICollectionView.
The taps and swipes are not getting recognized. Is there something obvious that I am missing?
Thanks.
Restarting the simulator worked for me.
Turns out the view was not responding to any gestures - scrolling, taps on buttons or the swipe actions. I deleted generated folders from ~/Library/Application Support/iPhone Simulator / 6.1/Applications and ~/Library/Developer/Xcode/DerivedData, reset the simulator settings (from iOS Simulator > Reset Contents and Settings), did a clean in xcode (Product > Clean) and ran the app again. The gestures are now recognized. I am not sure which of the above fixed the problem...it is possible that simply resetting the simulator's contents and settings would have been enough.
You just need to select Show Device Bezels:
Goto simulator > Window > Enable Show Device Bezels
Enjoy your swipe to back gesture.
add this method to your viewcontroller so your UICollectionView doesn't block other gestures
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return true;
}
In case you have already enabled Device Bezels from Window panel but still can't use swipe to go back gesture. Please refer to this answer.
All you need to do is restart the simulator and try to swipe from the real edge of the simulator.
First you Need To Add UITapGestureRecognizer Delegate method To .h
#interface ViewController : UIViewController<UIGestureRecognizerDelegate>
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doubleTapImgView:)];
doubleTap.numberOfTapsRequired = 2;
doubleTap.delegate = self;
- (void)doubleTapImgView:(UITapGestureRecognizer *)gesture
{
//Do What you want Here
}

iOS UItableview scrollToRowAtIndexPath not working anymore

This morning I just installed new Xcode which includes iOS 6.
I have a table view loaded with a plist file containing chapters and lines. Chapters define the sections.
The user selects chapter and line and the tableview is automatically scrolled to the correct position (in the viewDidLoad).
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:linePos inSection:chapterPos];
[self.tableView scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionTop animated:YES];
this works just great in iOS5 simulator.
Trying this in the iOS 6 simulator the scroll is not performed. I get no errors. I have checked, linePos and chapterPos receive correct values but the scroll is not performed.
Any ideas why ?
Objective-C:
[self.tableView reloadData];
dispatch_async(dispatch_get_main_queue(), ^{
NSIndexPath *rowIndexPath = [NSIndexPath indexPathForRow:3 inSection:0];
[self.tableView scrollToRowAtIndexPath:rowIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
});
Swift:
tableView.reloadData()
DispatchQueue.main.async {
let indexPath = IndexPath(row: linePos, section: chapterPos)
self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
}
For recent versions of iOS, please read Fyodor Volchyok's answer. Note that it's not marked as the accepted answer simply because at the time the question was first asked (Sept. 2012), the current answer was the working solution.
More recent versions of iOS also got the same problem which is now solved by Fyodor Volchyok's answer, so you should +1 his answer at that moment.
I found the answer. I have to first reload the data in the tableview
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:linePos inSection:chapterPos];
[self.tableView reloadData];
[self.tableView scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionTop animated:YES];
Even though I found the answer I don't know why it is working in iOS5 and not in iOS6.
EDIT
Perhaps I should add that even though it was working, I was still having a problem in displaying the last row and posted a question for that
UItableview scrollToRowAtIndexPath not displaying last row correctly
As #Raj also asked for it, I should say that I was triggering that in the viewDidLoad. To correct the problem of the last row not displaying correctly I had to put it in the viewDidAppear.
This works in iOS 12 and 13:
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.tableView.scrollToRow(at: IndexPath(row: 0, section: 1), at: .bottom, animated: true)
}
I ran into another issue (probably a bug) with scrollToRowAtIndexPath specifically on an iPhone X running ios11. My table has a few hundred sections and in collapsed mode ~10 would fit in the visible screen. As the indexPath got deeper, the scrolling gradually fell behind.
For example, when I wanted the search to find the item in row 30, the ScrollPositionTop would have one additional row before the actual row I expect to be at the top.
And as I tested searching for deeper rows, it started falling behind even more where for say anything past 100 rows deep or so, the expected row did not even come in the visible area.
The workaround I found so far is to say animated:NO for the scrolling within dispatch_async, then it works without any glitches.
I'm adding this answer as an addition to Fyodor Volchyok's answer. I also found that dispatching solves the issue. I was able to find a workaround that doesn't dispatch.
self.tableView.reloadData()
let index = // the desired index path
// For some reason, requesting the cell prior to
// scrolling was enough to workaround the issue.
self.tableView.cellForRowAtIndexPath(index)
self.tableView.scrollToRowAtIndexPath(index, atScrollPosition: .Top, animated: false)
After iOS7 the property automaticallyAdjustsScrollViewInsets of UIViewController default is YES. It will cause system to adjust the contentOffset of tableView when the view controller pushed. Even you call [self.tableView scrollToRowAtIndexPath:rowIndexPath atScrollPosition:UITableViewScrollPositionNone animated:NO]; in the viewWillAppear. The contentOffset also will be changed by system after viewWillAppear. So my solution is:
- (void)viewDidLoad {
[super viewDidLoad];
self.automaticallyAdjustsScrollViewInsets = NO;
/// any other codes
}
- (void)viewWillLayoutSubviews {
self.tableView.contentInset = UIEdgeInsetsMake(self.topLayoutGuide.length, 0, 0, 0);
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// change tableView data source
[self.tableView reloadData];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[self.dataSourceArray count] - 1 inSection:0];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:NO];
}
One more possible workaround is to call layoutIfNeeded before calling scrollToRowAtIndexPath.
[self.view layoutIfNeeded];
[self.tableView scrollToRowAtIndexPath...];
It worked for me in ios11
self.tableView.estimatedRowHeight = 0;
self.tableView.estimatedSectionFooterHeight = 0;
self.tableView.estimatedSectionHeaderHeight = 0
dispatch_async(dispatch_get_main_queue(), ^{
NSInteger numberOfSections = self.tableView.numberOfSections;
if (numberOfSections > 0)
{
NSInteger lastSection = numberOfSections - 1;
NSInteger lastRowInLastSections = [self.tableView numberOfRowsInSection:lastSection] - 1;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:lastRowInLastSections inSection:lastSection];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:isAnimated];
}
});
Fyodor Volchyok's answer in Swift:
tableView.reloadData()
let indexPath = NSIndexPath(forRow: linePos, inSection: chapterPos)
// make sure the scroll is done after data reload was finished
dispatch_async(dispatch_get_main_queue()) {
self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
}

Multiple UITextFields in a custom UITableViewCell

I have a UITableView that has 2 different customcell definitions. One is a single UITextField and the other has 4 UITextFields
userInteractionEnabled is manually set to enable cell level touch navigation, and I handle the UI interaction within didSelectRowAtIndexPath to the first responder to the relevant cell
This all worked fine when I was using just the one customcell (EditableCustomCell) with one UITextField (editableTextField), but now I have a customcell (LatLonCustomCell) with 4 UITextFields (degrees, minutes, seconds, cartesian), I cannot determine which field has been touched in order to set becomeFirstResponder
(currently I'm defaulting in the first textfield called degrees during debug)
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[prevField resignFirstResponder];
prevField.userInteractionEnabled = NO;
if(indexPath.section == kFirstSection && (indexPath.row == kLatitudeRow || indexPath.row == kLongitudeRow)) {
LatLonCustomCell *customCell = (LatLonCustomCell *)[MyTableView cellForRowAtIndexPath:indexPath];
currField = customCell.degrees; // need to set correct field here
} else {
EditableCustomCell *customCell = (EditableCustomCell *)[MyTableView cellForRowAtIndexPath:indexPath];
currField = customCell.editableTextField;
}
currFieldIndexPath = [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section];
currField.userInteractionEnabled = YES;
[currField becomeFirstResponder];
}
OK, so for those that come across this with the same or similar problem, I have finally made a breakthrough
I decided that I was going to need to capture the X/Y coordinates of the touch prior to the didSelectRowAtIndexPath being called. This way I could then determine which UITextField the touch occurred in by checking the touch against the "bounds" of the textfield
After some random searching, I found that a VERY easy way of capturing ANY touch event in the viewcontroller (as touchesBegan only occurred in the custom overridden UITableViewCell class and I knew not how to pass this back up the chain Cell > TableView > Scroll View > Controller)
By adding this to the viewDidLoad method:
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapGesture:)];
tapGesture.numberOfTapsRequired = 1;
// Pass the tap through to the UITableView
tapGesture.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:tapGesture];
This captures all touches, calling the handleTapGesture method
Then within this method it was simply a case of checking if the touch was within the bounds of the tableview, and if so, determine the indexPath for the point touched and then check against the bounds of the object required, below is a simplified version of what I came up with
-(void)handleTapGesture:(UITapGestureRecognizer *)tapGesture {
CGPoint tapLoc = [tapGesture locationInView:self.tableView];
if([MyTableView indexPathForRowAtPoint:tapLoc]) {
// Tap still handled by the UITableView delegate method
NSIndexPath *indexPath = [MyTableView indexPathForRowAtPoint:tapLoc];
if(indexPath.section == 0 && (indexPath.row == kLatitudeRow || indexPath.row == kLongitudeRow)) {
LatLonCustomCell *customCell = (LatLonCustomCell *)[MyTableView cellForRowAtIndexPath:indexPath];
UIScrollView *scrollView = (UIScrollView *)self.view;
CGRect rc;
// Degrees
rc = [customCell.degrees convertRect:[customCell.degrees bounds] toView:scrollView];
if (tapLoc.x >= rc.origin.x && tapLoc.y >= rc.origin.y && tapLoc.x <= (rc.origin.x + rc.size.width) && tapLoc.y <= (rc.origin.y + rc.size.height)) {
NSLog(#"touch within bounds for DEGREES");
touchField = customCell.degrees;
}
// Repeat for other textfields here ....
....
In my code I save the field within touchField, as within the didSelectRowAtIndexPath code, I am already handling prevField/currField values to control the enabling/disabling of userInteractionEnabled and to set the currField as becomeFirstReponder
Hope this proves helpful to someone :)
In the past when I have needed to check if a text box has been touched I checked if YourTextField.text.length > 0. If it is you can set becomeFirstResponder. Hope this helps.
Have you thought about using NSNotificationCenter to request notifications for UITextFieldTextDidBeginEditingNotification?
in viewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(textFieldBeganEditing)
name:UITextFieldTextDidBeginEditingNotification object:nil];
and then something like
-(void) textFieldBegainEditing: (NSNotification*) notification {
// [notification object] will be the UITextField
// do what you need to do with it (resign, become first responder)
}

Getting row of UITableView cell on button press

I have a tableview controller that displays a row of cells. Each cell has 3 buttons. I have numbered the tags for each cell to be 1,2,3. The problem is I don't know how to find on which cell a button is being pressed. I'm currently only getting the sender's tag when one of the buttons has been pressed. Is there a way to get the cell row number as well when a button is pressed?
You should really be using this method instead:
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
Swift version:
let buttonPosition = sender.convert(CGPoint(), to:tableView)
let indexPath = tableView.indexPathForRow(at:buttonPosition)
That will give you the indexPath based on the position of the button that was pressed. Then you'd just call cellForRowAtIndexPath if you need the cell or indexPath.row if you need the row number.
If you're paranoid, you can check for if (indexPath) ... before using it just in case the indexPath isn't found for that point on the table view.
All of the other answers are likely to break if Apple decides to change the view structure.
Edit: This answer is outdated. Please use this method instead
Try this:
-(void)button1Tapped:(id)sender
{
UIButton *senderButton = (UIButton *)sender;
UITableViewCell *buttonCell = (UITableViewCell *)[senderButton superview];
UITableView* table = (UITableView *)[buttonCell superview];
NSIndexPath* pathOfTheCell = [table indexPathForCell:buttonCell];
NSInteger rowOfTheCell = [pathOfTheCell row];
NSLog(#"rowofthecell %d", rowOfTheCell);
}
Edit: If you are using contentView, use this for buttonCell instead:
UITableViewCell *buttonCell = (UITableViewCell *)senderButton.superview.superview;
I would recommend this way to fetch indexPath of cell which has any custom subview - (compatible with iOS 7 as well as all previous versions)
-(void)button1Tapped:(id)sender {
//- (void)cellSubviewTapped:(UIGestureRecognizer *)gestureRecognizer {
// UIView *parentCell = gestureRecognizer.view.superview;
UIView *parentCell = sender.superview;
while (![parentCell isKindOfClass:[UITableViewCell class]]) { // iOS 7 onwards the table cell hierachy has changed.
parentCell = parentCell.superview;
}
UIView *parentView = parentCell.superview;
while (![parentView isKindOfClass:[UITableView class]]) { // iOS 7 onwards the table cell hierachy has changed.
parentView = parentView.superview;
}
UITableView *tableView = (UITableView *)parentView;
NSIndexPath *indexPath = [tableView indexPathForCell:(UITableViewCell *)parentCell];
NSLog(#"indexPath = %#", indexPath);
}
This doesn't require self.tablview either.
Also, notice the commented code which is useful if you want the same through a #selector of UIGestureRecognizer added to your custom subview.
There are two ways:
#H2CO3 is right. You can do what #user523234 suggested, but with a small change, to respect the UITableViewCellContentView that should come in between the UIButton and the UITableViewCell. So to modify his code:
- (IBAction)button1Tapped:(id)sender
{
UIButton *senderButton = (UIButton *)sender;
UITableViewCellContentView *cellContentView = (UITableViewCellContentView *)senderButton.superview;
UITableViewCell *tableViewCell = (UITableViewCell *)cellContentView.superview;
UITableView* tableView = (UITableView *)tableViewCell.superview;
NSIndexPath* pathOfTheCell = [tableView indexPathForCell:tableViewCell];
NSInteger rowOfTheCell = pathOfTheCell.row;
NSLog(#"rowofthecell %d", rowOfTheCell);
}
If you create a custom UITableViewCell (your own subclass), then you can simply call self in the IBAction. You can link the IBAction function to your button by using storyboard or programmatically when you set up the cell.
- (IBAction)button1Tapped:(id)sender
{
UITableView* tableView = (UITableView *)self.superview;
NSIndexPath* pathOfTheCell = [tableView indexPathForCell:self];
NSInteger rowOfTheCell = pathOfTheCell.row;
NSLog(#"rowofthecell %d", rowOfTheCell);
}
I assume you add buttons to cell in cellForRowAtIndexPath, then what I would do is to create a custom class subclass UIButton, add a tag called rowNumber, and append that data while you adding button to cell.
Another simple way:
Get the point of touch in tableView
Then get index path of cell at point
The index path contains row index
The code is:
- (void)buttonTapped:(id)sender {
UITapGestureRecognizer *tap = (UITapGestureRecognizer *)sender;
CGPoint point = [tap locationInView:theTableView];
NSIndexPath *theIndexPath = [theTableView indexPathForRowAtPoint:point];
NSInteger theRowIndex = theIndexPath.row;
// do your stuff here
// ...
}
Swift 3
Note: This should really go in the accepted answer above, except that meta frowns upon such edits.
#IBAction func doSomething(_ sender: UIButton) {
let buttonPosition = sender.convert(CGPoint(), to: tableView)
let index = tableView.indexPathForRow(at: buttonPosition)
}
Two minor comments:
The default function has sender type as Any, which doesn't have convert.
CGPointZero can be replaced by CGPoint()
One solution could be to check the tag of the button's superview or even higher in the view hierarchy (if the button is in the cell's content view).
I would like to share code in swift -
extension UITableView
{
func indexPathForCellContainingView(view1:UIView?)->NSIndexPath?
{
var view = view1;
while view != nil {
if (view?.isKindOfClass(UITableViewCell) == true)
{
return self.indexPathForCell(view as! UITableViewCell)!
}
else
{
view = view?.superview;
}
}
return nil
}
}
In swift:
#IBAction func buttonAction(_ sender: UIButton) {
guard let indexPath = tableView.indexPathForRow(at: sender.convert(CGPoint(), to: tableView)) else {
return
}
// do something
}

Is it possible to refresh a single UITableViewCell in a UITableView?

I have a custom UITableView using UITableViewCells.
Each UITableViewCell has 2 buttons. Clicking these buttons will change an image in a UIImageView within the cell.
Is it possible to refresh each cell separately to display the new image?
Any help is appreciated.
Once you have the indexPath of your cell, you can do something like:
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPathOfYourCell, nil] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
In Xcode 4.6 and higher:
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:#[indexPathOfYourCell] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
You can set whatever your like as animation effect, of course.
I tried just calling -[UITableView cellForRowAtIndexPath:], but that didn't work. But, the following works for me for example. I alloc and release the NSArray for tight memory management.
- (void)reloadRow0Section0 {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
NSArray *indexPaths = [[NSArray alloc] initWithObjects:indexPath, nil];
[self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
[indexPaths release];
}
Swift:
func updateCell(path:Int){
let indexPath = NSIndexPath(forRow: path, inSection: 1)
tableView.beginUpdates()
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic) //try other animations
tableView.endUpdates()
}
reloadRowsAtIndexPaths: is fine, but still will force UITableViewDelegate methods to fire.
The simplest approach I can imagine is:
UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:indexPath];
[self configureCell:cell forIndexPath:indexPath];
It's important to invoke your configureCell: implementation on main thread, as it wont work on non-UI thread (the same story with reloadData/reloadRowsAtIndexPaths:). Sometimes it might be helpful to add:
dispatch_async(dispatch_get_main_queue(), ^
{
[self configureCell:cell forIndexPath:indexPath];
});
It's also worth to avoid work that would be done outside of the currently visible view:
BOOL cellIsVisible = [[self.tableView indexPathsForVisibleRows] indexOfObject:indexPath] != NSNotFound;
if (cellIsVisible)
{
....
}
If you are using custom TableViewCells, the generic
[self.tableView reloadData];
does not effectively answer this question unless you leave the current view and come back. Neither does the first answer.
To successfully reload your first table view cell without switching views, use the following code:
//For iOS 5 and later
- (void)reloadTopCell {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
NSArray *indexPaths = [[NSArray alloc] initWithObjects:indexPath, nil];
[self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
}
Insert the following refresh method which calls to the above method so you can custom reload only the top cell (or the entire table view if you wish):
- (void)refresh:(UIRefreshControl *)refreshControl {
//call to the method which will perform the function
[self reloadTopCell];
//finish refreshing
[refreshControl endRefreshing];
}
Now that you have that sorted, inside of your viewDidLoad add the following:
//refresh table view
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:#selector(refresh:) forControlEvents:UIControlEventValueChanged];
[self.tableView addSubview:refreshControl];
You now have a custom refresh table feature that will reload the top cell. To reload the entire table, add the
[self.tableView reloadData]; to your new refresh method.
If you wish to reload the data every time you switch views, implement the method:
//ensure that it reloads the table view data when switching to this view
- (void) viewWillAppear:(BOOL)animated {
[self.tableView reloadData];
}
Swift 3 :
tableView.beginUpdates()
tableView.reloadRows(at: [indexPath], with: .automatic)
tableView.endUpdates()
Here is a UITableView extension with Swift 5:
import UIKit
extension UITableView
{
func updateRow(row: Int, section: Int = 0)
{
let indexPath = IndexPath(row: row, section: section)
self.beginUpdates()
self.reloadRows(at: [indexPath], with: .automatic)
self.endUpdates()
}
}
Call with
self.tableView.updateRow(row: 1)
Just to update these answers slightly with the new literal syntax in iOS 6--you can use Paths = #[indexPath] for a single object, or Paths = #[indexPath1, indexPath2,...] for multiple objects.
Personally, I've found the literal syntax for arrays and dictionaries to be immensely useful and big time savers. It's just easier to read, for one thing. And it removes the need for a nil at the end of any multi-object list, which has always been a personal bugaboo. We all have our windmills to tilt with, yes? ;-)
Just thought I'd throw this into the mix. Hope it helps.
I need the upgrade cell but I want close the keyboard.
If I use
let indexPath = NSIndexPath(forRow: path, inSection: 1)
tableView.beginUpdates()
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic) //try other animations
tableView.endUpdates()
the keyboard disappear