Fix a bug causing keyboard view offset to be incorrect (#204)

* Fix a bug causing keyboard view offset to be incorrect

In some rare cases, if the height of the view is a fractional point
(i.e., not a whole number), it would cause the views to not be offset
despite the keyboard being shown on top of them. This does not happen
with every fractional height. Different devices also behave a little
differently in seemingly identical layouts, due to their pixel density
being different.

The base issue is that, due to floating point rounding errors, two
values that _should_ be identical and pass the guard fail to do so,
because the lack of precision results in them not being equal. By
flooring the values, we can ignore really minor differences and ensure
rounding errors don't cause this issue.

* Unify bma_round methods to use correct calculation

Thanks to @diegosanchezr for the suggested improvement.

* Revert ChattoAdditions bma_round change

Unfortunately, removing this in favor of the Chatto version broke size
calculations, so putting it back...

* Switch to using infix operator to check float comparison

* Add utils to Chatto project
This commit is contained in:
Daniel Burgess 2016-08-22 10:46:32 -04:00 committed by Diego Sánchez
parent e881ae93aa
commit ab286307c3
4 changed files with 41 additions and 1 deletions

View File

@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
B3B1B0FF1D6B40DF00D1183D /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3B1B0FE1D6B40DF00D1183D /* Utils.swift */; };
C31E919A1BFF4CA300339585 /* BaseChatViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C31E91991BFF4CA300339585 /* BaseChatViewControllerTests.swift */; };
C321C3961BE78835009803D1 /* CollectionChangesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C321C3951BE78835009803D1 /* CollectionChangesTests.swift */; };
C321DDA91BE9649F00DE88CC /* BaseChatItemPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C321DD941BE9649F00DE88CC /* BaseChatItemPresenter.swift */; };
@ -48,6 +49,7 @@
/* Begin PBXFileReference section */
55E85D821BE390BE001885AD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
B3B1B0FE1D6B40DF00D1183D /* Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = "<group>"; };
C31E91991BFF4CA300339585 /* BaseChatViewControllerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseChatViewControllerTests.swift; sourceTree = "<group>"; };
C321C3951BE78835009803D1 /* CollectionChangesTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionChangesTests.swift; sourceTree = "<group>"; };
C321DD941BE9649F00DE88CC /* BaseChatItemPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseChatItemPresenter.swift; sourceTree = "<group>"; };
@ -188,6 +190,7 @@
C3E905041BE0521700C662A2 /* Info.plist */,
C342D0C01C638A2C008A4605 /* ReadOnlyOrderedDictionary.swift */,
C36281EC1BF10086004D6BCE /* SerialTaskQueue.swift */,
B3B1B0FE1D6B40DF00D1183D /* Utils.swift */,
C321DD931BE9649F00DE88CC /* Chat Items */,
C3E904AE1BE0509E00C662A2 /* ChatController */,
);
@ -349,6 +352,7 @@
C36281EB1BF0F62F004D6BCE /* DummyChatItemPresenter.swift in Sources */,
C3C7C3981CAC4BAC00A49929 /* ChatCollectionViewLayout.swift in Sources */,
C3C7C39B1CAC4BAC00A49929 /* KeyboardTracker.swift in Sources */,
B3B1B0FF1D6B40DF00D1183D /* Utils.swift in Sources */,
C342D0C11C638A2C008A4605 /* ReadOnlyOrderedDictionary.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

View File

@ -121,7 +121,7 @@ class KeyboardTracker {
guard let rect = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() else { return 0 }
guard rect.height > 0 else { return 0 }
let rectInView = self.view.convertRect(rect, fromView: nil)
guard rectInView.maxY >= self.view.bounds.height else { return 0 } // Undocked keyboard
guard rectInView.maxY >=~ self.view.bounds.height else { return 0 } // Undocked keyboard
return max(0, self.view.bounds.height - rectInView.minY - self.keyboardTrackerView.intrinsicContentSize().height)
}

32
Chatto/Source/Utils.swift Normal file
View File

@ -0,0 +1,32 @@
/*
The MIT License (MIT)
Copyright (c) 2015-present Badoo Trading Limited.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
import Foundation
private let scale = UIScreen.mainScreen().scale
infix operator >=~ { }
func >=~ (lhs: CGFloat, rhs: CGFloat) -> Bool {
return round(lhs * scale) >= round(rhs * scale)
}

View File

@ -66,6 +66,7 @@
AF937EAD0FD4F9788305ABD479F421A4 /* PhotosInputDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA74C6FA4698B48048CEF5C23B4D60FF /* PhotosInputDataProvider.swift */; };
B073E3DCBE4C1EAED2510C69D07A0D3B /* ExpandableTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96828BB92772CE300432BA86B596C687 /* ExpandableTextView.swift */; };
B1577264ED188FAC450DD92F624A2A6E /* PhotosInputCellProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3963A79061EE854E9B5C277DA6221143 /* PhotosInputCellProvider.swift */; };
B377A57F1D68EC1A000CDED8 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = B377A57E1D68EC1A000CDED8 /* Utils.swift */; };
B48B02953333C95136DDA71CA56C9271 /* BaseChatItemPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C09AD9E0C73B2D8A414CFEFF5030462C /* BaseChatItemPresenter.swift */; };
B7E8E79188BA84E1E762C4DE0D543EFC /* SerialTaskQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADD5EF621D4C97159780FBA704E1E7EE /* SerialTaskQueue.swift */; };
BB474BC0BBC8D55868A7734879874EAF /* BaseMessageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96402187D4C05CEFBCD217A5B52D41CE /* BaseMessageViewModel.swift */; };
@ -195,6 +196,7 @@
AF5BD772CABAA008A4802F6B3A73307E /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
B20598F484478DFEE1B31B07C6FA131F /* Pods-ChattoApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-ChattoApp.release.xcconfig"; sourceTree = "<group>"; };
B2DC506829E1BD918CEAF95D49131A91 /* PhotoMessageCollectionViewCellDefaultStyle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PhotoMessageCollectionViewCellDefaultStyle.swift; sourceTree = "<group>"; };
B377A57E1D68EC1A000CDED8 /* Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = "<group>"; };
B7FB07C7AA705C13B7F2884D8C4E4D52 /* PhotoMessageCollectionViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PhotoMessageCollectionViewCell.swift; sourceTree = "<group>"; };
BA74C6FA4698B48048CEF5C23B4D60FF /* PhotosInputDataProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PhotosInputDataProvider.swift; sourceTree = "<group>"; };
BB0F5037D43B05A9DB436F3D3E86BB28 /* BaseMessageCollectionViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BaseMessageCollectionViewCell.swift; sourceTree = "<group>"; };
@ -457,6 +459,7 @@
583960CE463732577E956CF9184EA67C /* Chatto.h */,
84AE77E2DC8C81FA8C4ABB08CEF0A2C4 /* ReadOnlyOrderedDictionary.swift */,
ADD5EF621D4C97159780FBA704E1E7EE /* SerialTaskQueue.swift */,
B377A57E1D68EC1A000CDED8 /* Utils.swift */,
80E8B3FFDB227A27832B4096E95169D8 /* Chat Items */,
AEFF9D5C30902A421C4BC13E21B200C8 /* ChatController */,
);
@ -923,6 +926,7 @@
FF617A66DF56CFD5A7F3CD5304CD4AB9 /* ChatItemProtocolDefinitions.swift in Sources */,
1293F88DD2651FCAFE9468D3172AE4CD /* Chatto-dummy.m in Sources */,
F438D6015DC57DA1095E60F73CCA5593 /* CollectionChanges.swift in Sources */,
B377A57F1D68EC1A000CDED8 /* Utils.swift in Sources */,
8AF84B9A19DF824F0F7905B1F0296E7B /* DummyChatItemPresenter.swift in Sources */,
EFF30D10A961BF864CDA109C126EA611 /* KeyboardTracker.swift in Sources */,
3AB11E8EAF8141F7F0A1E2D93FC4F37F /* ReadOnlyOrderedDictionary.swift in Sources */,