How to populate UITableView from the bottom upwards?
Solution 1
To populate UITableView
from the bottom:
- (void)updateTableContentInset {
NSInteger numRows = [self.tableView numberOfRowsInSection:0];
CGFloat contentInsetTop = self.tableView.bounds.size.height;
for (NSInteger i = 0; i < numRows; i++) {
contentInsetTop -= [self tableView:self.tableView heightForRowAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];
if (contentInsetTop <= 0) {
contentInsetTop = 0;
break;
}
}
self.tableView.contentInset = UIEdgeInsetsMake(contentInsetTop, 0, 0, 0);
}
To reverse the order of elements:
dataSourceArray = dataSourceArray.reverseObjectEnumerator.allObjects;
Swift 4.2/5 version:
func updateTableContentInset() {
let numRows = self.tableView.numberOfRows(inSection: 0)
var contentInsetTop = self.tableView.bounds.size.height
for i in 0..<numRows {
let rowRect = self.tableView.rectForRow(at: IndexPath(item: i, section: 0))
contentInsetTop -= rowRect.size.height
if contentInsetTop <= 0 {
contentInsetTop = 0
break
}
}
self.tableView.contentInset = UIEdgeInsets(top: contentInsetTop,left: 0,bottom: 0,right: 0)
}
Swift 3/4.0 version:
self.tableView.contentInset = UIEdgeInsetsMake(contentInsetTop, 0, 0, 0)
Solution 2
first reverse uitableview
tableView.transform = CGAffineTransformMakeScale (1,-1);
then reverse cell in cell create.
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
...
cell.contentView.transform = CGAffineTransformMakeScale (1,-1);
Solution 3
Swift 4.0 and 4.2 version
First reverse UITableView in viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
tableView.transform = CGAffineTransform(scaleX: 1, y: -1)
}
Then reverse the cell in cellForRowAt.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "MyTableViewCell", for: indexPath) as? MyTableViewCell else { fatalError() }
cell.contentView.transform = CGAffineTransform(scaleX: 1, y: -1)
return cell
}
Solution 4
Here is a refined solution of KlimczakM´s solution that works with autolayouted tableview cells (as well as the fixed ones). This solution also works with sections, section headers and section footers.
Swift 3.0:
func updateTableContentInset(forTableView tv: UITableView) {
let numSections = tv.numberOfSections
var contentInsetTop = tv.bounds.size.height -
(self.navigationBar?.frame.size.height ?? 0)
for section in 0..<numSections {
let numRows = tv.numberOfRows(inSection: section)
let sectionHeaderHeight = tv.rectForHeader(inSection: section).size.height
let sectionFooterHeight = tv.rectForFooter(inSection: section).size.height
contentInsetTop -= sectionHeaderHeight + sectionFooterHeight
for i in 0..<numRows {
let rowHeight = tv.rectForRow(at: IndexPath(item: i, section: section)).size.height
contentInsetTop -= rowHeight
if contentInsetTop <= 0 {
contentInsetTop = 0
break
}
}
// Break outer loop as well if contentInsetTop == 0
if contentInsetTop == 0 {
break
}
}
tv.contentInset = UIEdgeInsetsMake(contentInsetTop, 0, 0, 0)
}
NOTE:
Above code is untested but should work. Just make sure that you cope for the height of any navbar or tabbar and you'll be fine. In the code above i only do that for the navbar!
Solution 5
Don't bother to write the code by yourself. Why don't you use ReverseExtension. Its very easy and will give you all required results. Please follow this url https://github.com/marty-suzuki/ReverseExtension
Note: Whenever you need to add a new cell, please insert newly added model at zeroth index of datasource array, so new cell should add at bottom. Otherwise it would add the cell at top and you would get confused again.
kai Taylor
Updated on August 25, 2021Comments
-
kai Taylor over 2 years
is it possible to reverse the order of a tableView. I have searched a lot for a solution but all the results have not quite been a solution to what I am trying to achieve. They all suggest scrolling to the last position of a table with
scrollToRowAtIndexPath
and populating the data in reverse. But this doesn't work if the table content is dynamic and in some instances not all the cells have data. For example in a normal tableView the order is:
label 1
label 2
label 3
empty
empty
scroll direction
v
V
the desired result would be:
scroll direction
^
^empty
empty
empty
label 3
label 2
label 1
in this example if I used the suggested method of
scrollToRowAtIndexPath
and use the length of the array of objects, I would only get the third cell from the top. And end up with something like this:
unwanted outcome:
label 3
label 2
label 1
empty
empty
scroll direction
v
V
any help would be great thank you.