Need to display data from a single datasource into two different tables arranged just like columns. Here if first uitableview loads upto row 10 the next uitableview should start from row 11 and also if first uitableview scrolls the next uitableview should autoscroll the data based on the first one.
Well for loading your tables you can use cellForRowAtIndexPath method and use tags to differentiate tables and for table1 use [array1 objectAtIndex:indexPath.row] and for table2 use [array1 objectAtIndex:indexPath.row+10]
Now, about scrolling tables together. I've tried several methods but I succeed with this one:
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
NSArray *tableCells = [table1 visibleCells];
if ([tableCells count] > 0)
{
NSIndexPath *index = [table1 indexPathForCell:[tableCells objectAtIndex:0]];
[table2 scrollToRowAtIndexPath:index atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
}
But here what will happen is when you're done scrolling one table, your second table will start scrolling. If you need simultaneous scrolling, I tried - (void)scrollViewDidScroll:(UIScrollView *)scrollView method but it wasn't working smoothly as required. If this solution helps you, I'll be glad but if you find a better solution do let me know as well.
Related
I have a UITableView that is populated with cells of variable height. I would like the table to scroll to the bottom when the view is pushed into view.
I currently have the following function:
[self.table scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
I'm using autolayout, dynamic table cells and UITableViewAutomaticDimension as row height. I set estimatedRowHeight = 100
The above code works fine in viewDidLoad however this has the unfortunate side effect of displaying the top of the table when the view first appears and then jumping to the bottom. I would prefer it if the table view could be scrolled to the bottom before it appears.
Please note: I'm loading data from core data.
Any guidance would be much appreciated, even if it's just a case of telling me what I have is all that is possible.
Theoretically, the order of the calls is correct: viewDidLoad should be called before the view is rendered, so the only thing that comes to my mind is that probably scrollToRowAtIndexPath:atScrollPosition:animated: is asynchronous. Maybe there's something you can do with UIScrollViewDelegate (remember, UITableView inherits from UIScrollView) - https://developer.apple.com/documentation/uikit/uiscrollviewdelegate?language=objc
Maybe you can do something like hiding the view on onLoad and showing it on scrollViewDidScroll:. I don't have time to test and paste a snippet but... maybe it helps :) Good luck!
This seems pretty reliable...
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.estimatedRowHeight = 100;
[self.tableView performBatchUpdates:nil completion:^(BOOL b) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:numRows - 1 inSection:numSections - 1];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
}];
}
Replace numRows and numSections with your data count(s).
I've created a set of classes to simplify managing table views. One of the things they do is create a diff for a section based on what data is updated and then apply the correct insertions, deletions and moves.
This is all working great for most of my app, except for two uncooperative table views. Call them table A and table B. I've found a fix that works for each individually, but I can't fix both at the same time. I've checked that the diffs are being correctly generated, but for some reason I get different animations in each.
Both table A and table B are simply inserting rows. There are no deletions or moves.
In the below code BREAK_TABLE_A causes:
Table A - All rows in section=0 row>=1 (not row=0) to shift to the bottom while re-animating in from the top. Very ugly
Table B - A nice insertion animation
BREAK_TABLE_B causes:
Table A - A nice insertion animation
Table B - No animation. Just like reloadData
Ultimately, I would actually prefer the method in BREAK_TABLE_B because this allows me to keep the same cells for the same data, which means I can perform animations on those individual cells using configureCell:.
The code is relatively straightforward:
UITableViewRowAnimation animation = UITableViewRowAnimationFade;
...
[self.tableView beginUpdates];
NSMutableSet *insertedPaths...;
NSMutableSet *deletedPaths...;
NSMutableSet *refreshPaths...; // Will contain any cell that was present before and after the update.
[self.tableView moveRowsAtIndexPaths:... // Not executed in these examples
...
[self.tableView insertRowsAtIndexPaths:insertedPaths.allObjects withRowAnimation:animation];
[self.tableView deleteRowsAtIndexPaths:deletedPaths.allObjects withRowAnimation:animation];
if (BREAK_TABLE_A){
[self.tableView reloadRowsAtIndexPaths:refreshPaths.allObjects withRowAnimation:UITableViewRowAnimationNone];
} else { //BREAK_TABLE_B - I would prefer this solution if possible
for (NSIndexPath *path in refreshPaths){
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:path];
if (cell){
NSUInteger index = [newSection.rows indexOfObjectPassingTest:^BOOL(LQTableViewRow * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
return [obj.rowIdentifier isEqual:oldSection.rows[path.row].rowIdentifier];
}];
LQTableViewRow *row = newSection.rows[index];
[self configureCell:cell section:newSection row:row];
}
}
}
... update the actual data source ...
[self.tableView endUpdates];
In order to fix this, I've tried wrapping the above code in [CATransaction begin/commit/flush] as well as [UIView begin/commitAnimations] blocks. CATransaction freezes the app with no errors (probably waiting for some other animation) when using table B. UIView causes both views (and all others in the app) to animate incorrectly (cells fade in and animate from bottom to top of their final positions, rather than from the top to the bottom of the tableview).
I've also tried to load the views with dummy data such that they are as similar to each other as possible with the same weird results.
Well, it turns out that the crash when using the CATransaction led me to the answer. I had accidentally been doing [CATransaction begin] twice in one of my cells, instead of committing the transaction. Fixing that fixed the animations.
I have a segment control with a table view. When user clicks segment control, then table view changes data source. I would like table to scroll to last position user had seen.
For example: user was in segment 1 and looking at table view line 3.
segment 1 | segment 2
line 3
line 4
line 5
Then user clicked segment 2 then clicked back to segment 1. I want table view scroll to line 3.
Code is as below. In viewDidAppear I have same code to get lastSavedRow and call scrollToRowAtIndexPath. When app gets loaded the scrolling works. However, in segmentValueChanged action it doesn't roll to correct position. In debugger I am sure the lastSavedRow has correct number.
- (IBAction) segmentVauleChanged : (id)sender
{
// remember row number before segment value changes
NSArray *indexPaths = [self.tableView indexPathsForVisibleRows];
NSArray * sortedIndexPaths = [indexPaths sortedArrayUsingSelector:#selector(compare:)];
NSIndexPath *firstVisibleIndexPath = [sortedIndexPaths objectAtIndex:0];
// function to write row number and seg index to user default
[self saveScrollPositionInSegment: self.currentSegmentSelectedIndex row:firstVisibleIndexPath.row];
self.currentSegmentSelectedIndex = segmentController.selectedSegmentIndex;
[self.tableView reloadData];
// scroll to last saved position
int lastSavedRow = [self getScrollPositionInSegment:segmentController.selectedSegmentIndex];
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:lastSavedRow inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
Does anyone have same problem? Many thanks in advance!
The lastSavedRow will on the top of the current tableview. I think there maybe something wrong with the dealing with datasource. Maybe after change the datasource, the last postion the user seen was not the index you figured out!
If you provide more information or your example, we can help you to find out the mistake.
I would do the following.
1 .Call visibleCells before calling indexPathsForVisibleRows
[self.tableView visibleCells];
2.Look at the need for sorting the array before identifying firstVisibleIndexPath
3.reloadData is not synchronous so its possible that the table is not completed loading before you try to scroll to an index. So try to see if you can do the scrolling in one of the delegate functions instead of here. See this.
hackerinheels 's (3) is right. reloadData hasn't finished when scrolling table is called. So I added the code:
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
if (section == ([self.tableView numberOfSections] - 1)) {
//NSLog(#"finish loading");
// put the scrolling table call here: [self scrollTableView ];
}
return nil;
}
Thank you all for helping!
I'm trying to implement an infinite UITableView. I load some information from the server in chunks and I want to dynamically add this information to the tableview when user scrolls the table.The problem I'm facing : I have an initial tableview with 40 elements and then in scrollViewDidScroll I check if last visible row's indexPath == [myData count] - 20 (so when user has already scrolled half of the list I load next content) I load next 40 elements of content from the server and only when last visible row's indexPath == [myData count] -1 I actually reload the tableview. So as you see i make some eager caching in order to make tableview reloading faster.Everything work perfectly but when I begin to scroll my table really fast data stopped loading. It seems that this check: last visible row's indexPath == [myData count] - 20 has actually no chance to implement because of fast scrolling.I can't see any other obvious reasons for this. So has someone some answer for this weird problem?
P.S. Or may be I should try reloadRowsAtIndexPaths instead of reloading the whole table?
Maybe with this delegate you have a chance to do something in advance. There is also possible to reload only the visible rows which it's better than reload data.
-(void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView {
NSArray *paths = [self.tableView indexPathsForVisibleRows];
int tmprow = [[paths objectAtIndex:0] row];
}
I'm using a UITableView with static cells for the settings view of my application.
One of the sections of this table contains two cells, the second one only being visible when a UISwitch contained in the first one is turned on.
So the UISwitch's target is this:
- (void)notificationSwitchChanged:(id)sender
{
UISwitch* switch = (UISwitch*)sender;
self.bNotify = switch.on;
[self.settingsTable reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationTop];
}
I implemented numberOfRowsInSection: this way:
(NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
if (section != 1)
return [super tableView:tableView numberOfRowsInSection:section];
if (self.bNotify)
return 2;
return 1;
}
This "works", but the animation is faulty, making the first cell disappear or slide upwards halfway below the previous section or various stuff depending on the animation type I choose. The cleanest is UITableViewRowAnimationNone but is still not perfect.
If I scroll the section out of view and back it looks normal again.
EDIT: took a few screenshots of the problem:
I tried adding beginUpdates and endUpdates before and after reloadSections but it didn't change anything. Using reloadData instead of reloadSections works but there's no animation at all.
Is it because the table's cells are static or am I missing something?
I think this method should solve your problem.
[self.tableView insertSections:<#(NSIndexSet *)#> withRowAnimation:<#(UITableViewRowAnimation)#>];
Just update the data source (you dont have to because your are updating the section count depending on some flags) and call it.
Maybe you have to use this method instead.
[self.tableView insertRowsAtIndexPaths:<#(NSArray *)#> withRowAnimation:<#(UITableViewRowAnimation)#>];