TableView not scrolling in iOS11 - ios

I am using the text fields inside the table view. On keyboard next button, the focus get shift to the next text field, this working fine still the iOS 10. but on iOS 11 table is not getting scrolled. Following scroll help me to scroll the table view.
Below method to scroll tableview up on which text field is selected, write this code in textfield delegate method.
func textFieldDidEndEditing(textField: UITextField) {
// calculate the nsindexpath based on the textfield which is selected
tableView.scrollToRow(at: IndexPath(row: textField.tag + 1, section: 0), at: UITableViewScrollPosition.top, animated: true)
}

Related

Issue while scrolling to UITableView bottom

I have a chat application ,where in when I press the send button the table gets reloaded with new row and I am calling scroll to bottom function to scroll to the newly added cell. The problem is that my textview text does not get emptied until the tableview scrolls to the bottom. Is there any other way to perform these actions so as to reduce the time delay?
Scroll to botton code:
self.tableView.reloadData()
let section: Int = numberOfSections(in: self.tableView) - 1
let item: Int = tableView(self.tableView, numberOfRowsInSection:section) - 1
let lastIndexPath = IndexPath(item: item, section: section)
self.tableView.scrollToRow(at: lastIndexPath, at: .bottom, animated: false)
When I remove the above code, the textview gets emptied instantly
The issue :
Make sure that you call reloadData() on the main thread. Doing it in a background thread will often cause graphical delays and may even crash the application.
Also, where do you empty the textview?

iOS UITableView scrolling insets while filtering

I have some problem with UITableView scrolling. This is my simple screen where I have UITextField and UITableView with cells. When user type something in UITextField app filters list of items and reloads UITableView. And it is working as expected.
On the right screen you can see how UITableView looks when I scroll. Cells go under UITextField.
Let's assume I scrolled some cell and If I start to type something in UITextField I got list of filtered cells but some of them are under UITextField and I can't scroll them down.
By default the table's scroll offset doesn't change when you reload the table with new set of row data. You need to scroll back to top after reloading the table :
self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0),
at: .top,
animated: true)
and if you don't have a default place-holder cell to represent "No Matching Results" when there are no results and thus no cells to represent at Index (0,0) then add following condition before the above code to safeguard a crash:
guard cellResults.count > 0 else { return }
First of all your UITextField contained on tableview header view? UITableView need scrolling with table or not?
If your need always show first cell when user input something in UITextField, i recommend it with RxSwift like this
textField
.rx.text
.orEmpty
.debounce(0.1, scheduler: MainScheduler.instance)
.distinctUntilChanged()
.subscribe(onNext: { [unowned self] query in
//TODO: Do something with you table, for example
// self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
// or update tableView.
})
.disposed(by: disposeBag)

How to scroll at the bottom with animated in UITableView swift 3

How to animate the footer view a table view when the UItableView reloads?
I am trying to append an element to the tableView and when the table view reloads the footer view should come with some animation. And also if the table view contents exceeds the screen size the footer view should stick with bottom of the screen. Here is my try:
tableView.beginUpdates()
self.familyAModelArray.append(self.childAModelArray)
tableView.endUpdates()
Note: Here i want to append an object to an array which is the content of the UITableView and reload the TableView. Thanks in advance!
To animate the insert action, you need to call insertRowsAtIndexPaths method with row animation.
After adding table cell elements to your array, you must calculate the index paths for the new cells to be displayed, and create an array of them, like this
let indexes = [IndexPath(row: 0, section: 0), IndexPath(row: 1, section: 0)]
Then simply call the following method to animate the insertion
tableView.beginUpdates()
tableView.insertRowsAtIndexPaths(indexes, withRowAnimation: .Fade)
tableView.endUpdates()
If you want the footer view to stick on the bottom of your screen, then it shouldn't be a footer view. it should be a custom UIView that is pinned to your view controller's view. Whenever you call a reloadData() on your tableView, you can likewise call a present/animate function on your new custom view that you pinned to the bottom & animate it on / off the screen.
I have solved this by using animation on UIView when the UITableView reloads after appending the rows.
UIView.transition(with: tableView, duration: 0.2, options: .curveEaseIn, animations: {self.tableView.reloadData()}, completion:{ (success) in
if success {
if self.familyAModelArray.count >= 3{
self.scrollToBottom()
}
}
})
And if length of my array is greater than 3 the footer view stick at the bottom by scrolling the UITableView to the top .
func scrollToBottom(){
DispatchQueue.global(qos: .background).async {
let indexPath = IndexPath(row: self.familyAModelArray.count-1, section: 0)
self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
}
}
This solution has given a nice look for my table view.

Prevent uitableview from scrolling after removing last cell

I have a tableview (style - grouped) which contains more rows than can fit into its frame so you have to scroll to see the last row. When I delete the last row the tableview scrolls its content down so the new last row is at the bottom of the frame (kind of fill the empty space).
How can I prevent a UITableView from scrolling after I delete the last row in it? I want it to keep the empty space and do not scroll automatically.
I have tried to set content insets but it doesn't seem to prevent scrolling unfortunately.
EDIT: My code for removing the row:
func removeLastRow() {
let indexPath = IndexPath.init(row: self.messages.count - 1, section: 0)
self.messages.removeLast()
CATransaction.begin()
self.tableView.beginUpdates()
CATransaction.setCompletionBlock { () -> Void in
// do stuff, add new rows
}
self.tableView.deleteRows(at: [indexPath], with: .left)
self.tableView.endUpdates()
CATransaction.commit()
}
Retreive the cells size before deleting by calling tableView:heightForRowAt: and after deleting, set the vertical content offset of your table view manually to the current vertical content offset, plus the height of the cell.
let deletedCellHeight = tableView.heightForRowAt(indexPath)
Then:
tableView.contentOffset.x += deletedCellHeight

UITableView jumping to top on endUpdates while typing inside a cell on iOS 8 auto height [duplicate]

This question already has answers here:
reloadData() of UITableView with Dynamic cell heights causes jumpy scrolling
(22 answers)
Closed 4 years ago.
I am using iOS 8 self-sizing cells (tableView.rowHeight = UITableViewAutomaticDimension and tableView:estimatedHeightForRowAtIndexPath:) combination. It works great until I start typing something inside a cell. When I'm typing, I'm calling beginUpdates/endUpdates pair to resize my cell (text view grows as I type and shrinks as I delete) but each call results in a bad jump to top of the table view. If I remove the beginUpdates/endUpdates pair then it doesn't jump but my cell doesn't resize as I type.
Here is a demonstration of the issue:
How can I get my cell to resize correctly as I type while not jumping to the top of the table view? I am only targeting iOS >= 8 so I don't need any kind of iOS 7 compatibility.
I was implementing the exactly the same thing for chat app and getting the same issue as you are getting now. This thing helped me out. Let me know if this works for you too.
UIView.setAnimationsEnabled(false)
tableView.beginUpdates()
cell.textView.scrollRangeToVisible(NSMakeRange(cell.textView.text.characters.count-1, 0))
tableView.endUpdates()
UIView.setAnimationsEnabled(true)
tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: false)
I found solution from Manoj Aher to work fine - text doesn't jump at all. But in my case I had to extend for situations when user might type much more text (so that the table cell is bigger than the visible part of the table) and then returns to edit this text somewhere at the beginning or in the middle. So I had to scroll the table cell to Top or Middle depending on where the user is typing to keep the typing position visible.
First, remember the indexPath for the cell in any convenient way. For example:
var cellIndexChosenForEdition: NSIndexPath
...
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
cellIndexChosenForEdition = indexPath
...
}
In shouldChangeTextInRange or any other method which is called when user types (shown here method will be called when your view controller conforms to UITextViewDelegate protocol):
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
...
UIView.setAnimationsEnabled(false)
MyTableView.beginUpdates()
MyTableView.endUpdates()
UIView.setAnimationsEnabled(true)
if let textStartPosition: UITextPosition = textView.selectedTextRange?.start {
let cursorPosition = textView.offsetFromPosition(textView.beginningOfDocument, toPosition: textStartPosition)
if textView.text.characters.count - cursorPosition < 170 {
table_create_issue.scrollToRowAtIndexPath(cellIndexChosenForEdition, atScrollPosition: .Bottom, animated: false)
} else if cursorPosition > 200 {
table_create_issue.scrollToRowAtIndexPath(cellIndexChosenForEdition, atScrollPosition: .Middle, animated: false)
} else {
table_create_issue.scrollToRowAtIndexPath(cellIndexChosenForEdition, atScrollPosition: .Top, animated: false)
}
}
...
}
*constants 200 and 170 should be changed to fit your concrete situation
**I didn't use scrollRangeToVisible because my textView height is always equal to cell height and never scrolls.
I'm having the same problem, and have been able to minimize (but not eliminate) the jumping by only doing the resize/update notification when the intrinsic size of the content has actually changed, e.g.:
Swift
var textViewHeight: CGFloat = 0.0 // Set in viewWillAppear as below
...
func textViewDidChange(textView: UITextView) {
let newHeight = textView.intrinsicContentSize().height
if textViewHeight != newHeight{
textViewHeight = newHeight
tableView.beginUpdates()
tableView.endUpdates()
}
}
Objective-C
CGFloat textViewHeight = 0.0; // Set in viewWillAppear as below
...
(void)textViewDidChange:(UITextView *)textView {
CGFloat newHeight = [textView intrinsicContentSize].height;
if (textViewHeight != newHeight){
textViewHeight = newHeight
[tableView beginUpdates];
[tableView endUpdates];
}
}
Are your reseting frame of Table View Cell on text begin editing? If yes, then you can check your variables sometimes due to memory allocation variables deallocate. Use break points and check variable values that can not be change according your requirement.
Auto layout have some drawback associated with it. When you start typing it jump because all other cell are adjusting their size so it will be better if you calculate the dimensions of cell on runtime only.

Resources