hackiftekhar / IQKeyboardManager

Codeless drop-in universal library allows to prevent issues of keyboard sliding up and cover UITextField/UITextView. Neither need to write any code nor any setup required and much more.
MIT License
16.45k stars 2.41k forks source link

UITableView header offset not calculated correctly when keyboard is dismissed #868

Closed yyu1 closed 6 years ago

yyu1 commented 7 years ago

In my ViewController, I have a UITableView and UISearchController.

For the UITableView, I have: tableView.tableHeaderView = searchController.searchBar

Now, I have isolated the issue to what appears to be when scope is enabled. If I have: searchController.searchBar.scopeButtonTitles = ["Scope1", "Scope2"] Then, if I click the searchBar, then dismiss the Keyboard, the UITableView's offset becomes incorrect and the UISearchBar stays hidden all the way on the top. If I do not include the scope, the offset is calculated correctly when the keyboard is dismissed.

It seems that when scope is enabled for UISearchBar, the height of the scope buttons is not taken into account when resetting the UITableView offset when keyboard is dismissed.

yyu1 commented 7 years ago

I did a bit of testing.

WITHOUT IQKeyboardManager when searchBar is not active (scope bar is hidden), the contentInset of UITableView is: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0) when searchBar is active, the contentInset is: UIEdgeInsets(top: 44.0, left: 0.0, bottom: 0.0, right: 0.0) when searchBar becomes inactive again, contentInset returns to original of: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)

WITH IQKeyboardManager when searchBar is not active (scope bar is hidden), the contentInset of UITableView is: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0) when searchBar is active, the contentInset is: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0) when searchBar becomes inactive again, contentInset becomes: UIEdgeInsets(top: -44.0, left: 0.0, bottom: 0.0, right: 0.0)

So it looks like there is some issues due to both the searchBar setting the contentInset of UITableView to accommodate the scope bar, as well as IQKeyboardManager trying to set the contentInset of the UITableView.

hackiftekhar commented 7 years ago

the IQKeyboardManager sometimes change tableView content inset, so there might be an issue with library code.

hackiftekhar commented 7 years ago

btw thanks for this info, it really help me to understand the problem.

hackiftekhar commented 7 years ago

hmm I checked the code and library was only manipulating .bottom value, I'm not sure why .top value is updating.

yyu1 commented 7 years ago

Here are some logs from the debug mode.
Note that the only user input I did here was click on the searchBar (did not dismiss the keyboard yet or input anything into the search bar).

The contentOffset reported by IQKeyboardManager was always {0,0}, until when it says the "Restoring" part, where contentOffset becomes {0,-44}.

Hope this helps a bit more

IQKeyboardManager: ** keyboardWillShow started ** IQKeyboardManager: UIKeyboard Size : (375.0, 216.0) IQKeyboardManager: ** keyboardWillShow ended: 0.000297550999675877 seconds ** IQKeyboardManager: ** textFieldViewDidBeginEditing started ** IQKeyboardManager: ** addToolbarIfRequired() started ** IQKeyboardManager: Found 0 responder sibling(s) IQKeyboardManager: ** addToolbarIfRequired() ended: 0.00396198999987973 seconds ** IQKeyboardManager: Saving <<UITabBarController: 0x7fc855406f20> 0x00007fc855406f20> beginning frame : (0.0, 0.0, 375.0, 667.0) IQKeyboardManager: ** adjustFrame() started ** IQKeyboardManager: Need to move: -333.0 IQKeyboardManager: Saving <<UITableView: 0x7fc855813800; frame = (16 72; 343 332); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x61800005d550>; layer = <CALayer: 0x618000228f00>; contentOffset: {0, 0}; contentSize: {343, 312752}> 0x00007fc855813800> contentInset : UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0) and contentOffset : (0.0, 0.0) IQKeyboardManager: <<UITableView: 0x7fc855813800; frame = (16 72; 343 332); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x61800005d550>; layer = <CALayer: 0x618000228f00>; contentOffset: {0, 0}; contentSize: {343, 312752}> 0x00007fc855813800> old ContentInset : UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0) IQKeyboardManager: <<UITableView: 0x7fc855813800; frame = (16 72; 343 332); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x61800005d550>; layer = <CALayer: 0x618000228f00>; contentOffset: {0, 0}; contentSize: {343, 312752}> 0x00007fc855813800> new ContentInset : UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0) IQKeyboardManager: ** adjustFrame() ended: 0.00162764700053231 seconds ** IQKeyboardManager: ** textFieldViewDidBeginEditing ended: 0.00703886700011935 seconds ** IQKeyboardManager: ** textFieldViewDidBeginEditing started ** IQKeyboardManager: ** addToolbarIfRequired() started ** IQKeyboardManager: Found 0 responder sibling(s) IQKeyboardManager: ** addToolbarIfRequired() ended: 0.000214777999644866 seconds ** IQKeyboardManager: ** adjustFrame() started ** IQKeyboardManager: Need to move: -333.0 IQKeyboardManager: Restoring <<UITableView: 0x7fc855813800; frame = (16 72; 343 332); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x61800005d550>; layer = <CALayer: 0x618000228f00>; contentOffset: {0, -44}; contentSize: {343, 312752}> 0x00007fc855813800> contentInset to : UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0) and contentOffset to : (0.0, 0.0) IQKeyboardManager: ** adjustFrame() ended: 0.00164268499975151 seconds ** IQKeyboardManager: ** textFieldViewDidBeginEditing ended: 0.00198582899975008 seconds ** IQKeyboardManager: ** keyboardDidShow started ** IQKeyboardManager: ** keyboardDidShow ended: 6.50069996481761e-05 seconds ** IQKeyboardManager: ** keyboardWillShow started ** IQKeyboardManager: UIKeyboard Size : (375.0, 260.0) IQKeyboardManager: ** adjustFrame() started ** IQKeyboardManager: Need to move: -289.0 IQKeyboardManager: ** adjustFrame() ended: 8.45160002427292e-05 seconds ** IQKeyboardManager: ** keyboardWillShow ended: 0.000217738000173995 seconds ** IQKeyboardManager: ** keyboardDidShow started ** IQKeyboardManager: ** keyboardDidShow ended: 7.1368999670085e-05 seconds **

hackiftekhar commented 7 years ago

hmm, as we can clearly see when IQKeyboardManager get your tableView.contentInset then it get's 0,0,0,0 this is why there might be some conflict.

yyu1 commented 7 years ago

So do you think this is due to things happening in this order?

  1. IQKeyboardManager grabs contentInset
  2. TableView adjusts contentInset due to scope bar appearing
  3. IQKeyboardManager restores contentInset, not knowing that TableView has changed the contentInset since it was last recorded in step 1.
hackiftekhar commented 7 years ago

I think Yes, it's doing something like that but needs investigation for exact steps.

yyu1 commented 7 years ago

Any update on this?

huzhiqin commented 7 years ago

Anybody can deal with it?

hackiftekhar commented 6 years ago

Nope, no updates on this issue till yet.

hackiftekhar commented 6 years ago

Can you guys now check with the new logic implementation, code is in master now. Let's see if that works for you.

hackiftekhar commented 6 years ago

I checked the latest version and it doesn't reproduce this issue neither with iOS11 nor with iOS10. If someone still have this issue let me know.