Center Cell UITableView When Scrolling Is Finished - ios

I have a UITableView, and I don't want it to stop between two cells when it stops after scrolling. So I need to move the cell which is the nearest of the Y center of the screen, when the velocity of the UITableView is less than a given value.
I'm sure I'm not the first who wants this effect, but I didn't find anything in my research. There must be a word for this that I don't know. Does someone have a link or something ?
I tried to do this on my own, but I don't find how to get the cell. I used tableView.indexPathsForVisibleRows(), so I have an array of indexPaths, but now I don't know how to call the corresponding cell. There is cellForRowAtIndexPath, but this method creates a new cell, doesn't it ?

You need to implement -scrollViewWillEndDragging:withVelocity:targetContentOffset: in your table view delegate, just as in this other question here.
Basically, this method allows you to tweak the position where the velocity scroll will halt.
I can't help you more with code without knowing the structure of your table view (cells of variable height?).

Try adding this to your ViewDidLoad:
self.tableView.bounces = false

Related

How to determine whether the user has scrolled past the first cell?

On iOS, when you append something to the beginning of UITableView's data source, the cell will "animate in" and push the rest of the cells down only if the user is already scrolled to the top. When the user is scrolled down farther down the list and a new item gets appended to the top, iOS does not automatically move the cells down.
When a new cell comes in from the top, how do I determine between the two?
My use case is that when the user has scrolled down past the iOS point, I can display a "new item above" button for the user to click . (similar to Twitter)
I'm using dynamic height for cells, so hard coding the scrollView by pixel isn't the most ideal way. I'd like to utilize iOS's way to determine it.
There is an array available of all visible cells' index paths called indexPathsForVisibleRows. You can access that property and check to see whether or not your first row is one of them, and go from there. You can also access visibleCells property to get the actual UITableViewCells themselves.
How to determine whether the user has scrolled past the first cell: a UITableView is a subclass of UIScrollView, so you can just look at the contentOffset property.
I'm not exactly sure that that's enough to accomplish what you want though. You could also maybe take advantage of the fact that tableView's cellForRowAtIndexPath: method only returns a cell if it's visible, and request the first cell. I've never tried implementing something like this before though so there might be a better approach.

UITableView how to continue scrolling after reload

I have a UITableView in my application. When the table is scrolled almost to the end, I download more data and reload the table.
If the tableView was scrolling, at the time I call [tableView reloadData]; scrolling stops. How can I achieve effect of not stopping the scroll meanwhile reloadData? I think I need to somehow save scrolling speed and then restore it, but how to do this?
P.D. I really searched this question before asking.
I thing, this method (insertRowsAtIndexPaths:withRowAnimation:) is the key.
There is a use case and a nice tip described on SO: the use case and the tip.
Since UITableView is subclass of UIScrollView, you can use UIScrollViewDelegate's scrollViewWillEndDragging:withVelocity:targetContentOffset:
method to determine how far it is supposed to scroll and then after table reload call setContentOffset:animated: with that target offset (or beginning/ending of tableview if it becomes smaller) to simulate continued scrolling
EDIT: since your targetContentOffset is probably going to be CGRectZero, you will have to recalculate it somehow using velocity from the same method
if i am not wrong you are looking for a function call Lazy load. I can recommend you to search SVPullToRefresh
here!

deleteRowsAtIndexPaths resets custom cells

I'm relatively new to Swift and iOS and I have one issue - I have a custom SwipeCell class that extends UITableViewCell. It's a cell that can be swiped left and right, and has buttons on each side. For some reason if I made the buttons out of the frame of the cell when user swipes the cell they would appear but could not call an action, so my solution was to make cell wider than it is (so buttons can fit in it). Because it was done this way my cell has to have an offset by default for the total width of the buttons of the left (let's say 100), so it's position is X:-100.
And that's fine, and everything works fines with the cells, however there is one huge issue - if I call the deletion of any cell from the tableView like this
tableView.deleteRowsAtIndexPaths([tableView.indexPathForCell(activeCell)!], withRowAnimation: .None)
tableView then deletes the cell, and all of the other cells that are currently visible (doesn't happen with cells above or below the screen bounds) get moved to X:0 instead of staying at X:-100, so I assume that deleteRowsAtIndexPaths calls some function that resets the visible cells positions to 0,0. I'm currently setting swipe cells positions with layoutSubviews() since the number of buttons is dynamic and couldn't be determined upfront, but layoutSubviews is not the function where the bug happens.
So to sum up question - what function does deleteRowsAtIndexPaths call after deleting a cell that resets/redraws the visible cells?
deleteRowsAtIndexPaths deletes a row(s) from the tableView. This is handled internally by iOS. From Apple documentation:
Deletes the rows specified by an array of index paths, with an option
to animate the deletion.
Another interesting thing to note here is that this method does not modify your model (object that holds data used by your table view cells to render on themselves). You have to do that yourself. The cells are deleted, but if you call reloadData without deleting the row from your Model, cell will reappear.
Expect that cells get deleted and created all the time. Cells are very, very temporary objects. Write the code to create one when needed, and don't make any assumptions. Don't assume the cell is there later, don't assume it's in the same row, don't assume it displays the same data (because cells are recycled).
Since I could find out what happens inside of deleteRowAtIndexPaths, and why it changes frames of each Cell, I decided to just do my own function that deletes a row, by obtaining cells with tableView.visibleCells, and then just moving cells bellow the deleted cell up by a height of deleted cell. Thank you all for trying to help me, and especially thanks to Abhinav who told me that it was handled internally, which help me decide to write a custom code for the deletion.

UITableView initial row selection

Maybe I'm missing something obvious, but I'm have a hard time programmatically setting the row selection in a tableView. The goal is to simply have a tableView open with a row already selected. The problem appears to be that I have to wait until the tableView is fully loaded before I can modify the selection.
I've read various strategies such as calling reloadData for the tableView in the viewController's viewWillAppear method, then immediately calling selectRowAtIndexPath for the target row. But when I do that, I get a range exception because the tableView has zero rows at that point. The UITableViewDelegate methods (numberOfRowsInSection, etc.) don't appear to be called immediately in response to reloadData (which makes sense if the table rows are drawn "lazily").
The only way I've been able to get this to work is to call selectRowAtIndexPath after a short delay, but then you can see the tableView scroll the selected row into view.
Surely, there's a better way of doing this?
Well, you can use another strategy. You can create a hidden table view, configure how you want and than show to user. Use the tableview.hidden = YES.

How to notice if a UITableViewCell has left the visible area?

I'm stuck with the problem that I want to know in my UITableView if a specific UITableViewCell, let's say the first, is still visible or already off the visible area.
I would also be ok to know if the cell of interest is now beeing reused at an other indexPath of the table.
One of my - later and frustrated approaches - was to have a thread that knows the first cell object and frequently pings it to check if a value I did set in the cell changed. Obviously a not so good solution.
Andy ideas how to do this right?
Remember that UITableView is UIScrollView subclass and its delegate also confirms to UIScrollViewDelegate protocol as well.
So in your table delegate you can implement scrollViewDidScroll: method and check contentOffset - if it's more then first cell height then first cell is not visible. You can also get the array off all currently visible cells using -visibleCells method, but I think knowing contentOffset should be enough.

Resources