Skip to content

Commit 89a0830

Browse files
committed
Revert code indentation and #98
1 parent 62e9c99 commit 89a0830

File tree

4 files changed

+137
-152
lines changed

4 files changed

+137
-152
lines changed

Example/Podfile.lock

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ SPEC CHECKSUMS:
5353
ManualLayout: 68ac8cfa6b5f656f7a9fadec3730208b95986880
5454
ReusableKit: e5f853ad4652e411f96b6119b2488afa12929be6
5555
RxCocoa: 3f79328fafa3645b34600f37c31e64c73ae3a80e
56-
RxKeyboard: 63595f98880901578c019beabc4df74b424ebe1d
56+
RxKeyboard: aefd4787ca8be28a4470cb871141fb50e105f900
5757
RxRelay: 8d593be109c06ea850df027351beba614b012ffb
5858
RxSwift: c14e798c59b9f6e9a2df8fd235602e85cc044295
5959
SnapKit: 97b92857e3df3a0c71833cce143274bf6ef8e5eb

Package.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import PackageDescription
55
let package = Package(
66
name: "RxKeyboard",
77
platforms: [
8-
.iOS(.v10)
8+
.iOS(.v9)
99
],
1010
products: [
1111
.library(name: "RxKeyboard", targets: ["RxKeyboard"]),

RxKeyboard.podspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ Pod::Spec.new do |s|
1515
s.dependency 'RxSwift', '~> 6.0'
1616
s.dependency 'RxCocoa', '~> 6.0'
1717

18-
s.ios.deployment_target = '10.0'
18+
s.ios.deployment_target = '9.0'
1919
end

Sources/RxKeyboard/RxKeyboard.swift

+134-149
Original file line numberDiff line numberDiff line change
@@ -13,170 +13,155 @@ import RxCocoa
1313
import RxSwift
1414

1515
public protocol RxKeyboardType {
16-
var frame: Driver<CGRect> { get }
17-
var visibleHeight: Driver<CGFloat> { get }
18-
var willShowVisibleHeight: Driver<CGFloat> { get }
19-
var isHidden: Driver<Bool> { get }
16+
var frame: Driver<CGRect> { get }
17+
var visibleHeight: Driver<CGFloat> { get }
18+
var willShowVisibleHeight: Driver<CGFloat> { get }
19+
var isHidden: Driver<Bool> { get }
2020
}
2121

2222
/// RxKeyboard provides a reactive way of observing keyboard frame changes.
2323
public class RxKeyboard: NSObject, RxKeyboardType {
2424

25-
// MARK: Public
26-
27-
/// Get a singleton instance.
28-
public static let instance = RxKeyboard()
29-
30-
/// An observable keyboard frame.
31-
public let frame: Driver<CGRect>
32-
33-
/// An observable visible height of keyboard. Emits keyboard height if the keyboard is visible
34-
/// or `0` if the keyboard is not visible.
35-
public let visibleHeight: Driver<CGFloat>
36-
37-
/// Same with `visibleHeight` but only emits values when keyboard is about to show. This is
38-
/// useful when adjusting scroll view content offset.
39-
public let willShowVisibleHeight: Driver<CGFloat>
40-
41-
/// An observable visibility of keyboard. Emits keyboard visibility
42-
/// when changed keyboard show and hide.
43-
public let isHidden: Driver<Bool>
44-
45-
// MARK: Private
46-
47-
private let disposeBag = DisposeBag()
48-
private let panRecognizer = UIPanGestureRecognizer()
49-
50-
// MARK: Initializing
51-
52-
override init() {
53-
54-
let defaultFrame = CGRect(
55-
x: .zero,
56-
y: UIScreen.main.bounds.height,
57-
width: UIScreen.main.bounds.width,
58-
height: .zero
59-
)
60-
61-
let frameVariable = BehaviorRelay<CGRect>(value: defaultFrame)
62-
63-
frame = frameVariable.asDriver().distinctUntilChanged()
64-
visibleHeight = frame.map { UIScreen.main.bounds.height - $0.origin.y }
65-
66-
willShowVisibleHeight = visibleHeight
67-
.scan((visibleHeight: .zero, isShowing: false)) { lastState, newVisibleHeight in
68-
(visibleHeight: newVisibleHeight, isShowing: lastState.visibleHeight <= .zero && newVisibleHeight > .zero)
69-
}
70-
.filter { $0.isShowing }
71-
.map { $0.visibleHeight }
72-
73-
isHidden = visibleHeight
74-
.map { $0 <= .ulpOfOne }
75-
.distinctUntilChanged()
76-
77-
super.init()
78-
79-
// keyboard will change frame
80-
let willChangeFrame = NotificationCenter.default.rx.notification(.keyboardWillChangeFrame)
81-
.map { notification -> CGRect in
82-
let rectValue = notification.userInfo?[String.keyboardFrameEndKey] as? NSValue
83-
return rectValue?.cgRectValue ?? defaultFrame
84-
}
85-
.map { frame -> CGRect in
86-
if frame.origin.y < .zero { // if went to wrong frame
87-
var newFrame = frame
88-
newFrame.origin.y = UIScreen.main.bounds.height - newFrame.height
89-
return newFrame
90-
}
91-
return frame
92-
}
93-
94-
// keyboard will hide
95-
let willHide = NotificationCenter.default.rx.notification(.keyboardWillHide)
96-
.map { notification -> CGRect in
97-
let rectValue = notification.userInfo?[String.keyboardFrameEndKey] as? NSValue
98-
return rectValue?.cgRectValue ?? defaultFrame
99-
}
100-
.map { frame -> CGRect in
101-
if frame.origin.y < .zero { // if went to wrong frame
102-
var newFrame = frame
103-
newFrame.origin.y = UIScreen.main.bounds.height
104-
return newFrame
105-
}
106-
return frame
107-
}
108-
109-
// pan gesture
110-
let didPan = panRecognizer.rx.event
111-
.withLatestFrom(frameVariable.asObservable()) { ($0, $1) }
112-
.flatMap { (gestureRecognizer, frame) -> Observable<CGRect> in
113-
guard case .changed = gestureRecognizer.state,
114-
let window = UIApplication.shared.windows.first,
115-
frame.origin.y < UIScreen.main.bounds.height else {
116-
return .empty()
117-
}
118-
119-
let origin = gestureRecognizer.location(in: window)
120-
var newFrame = frame
121-
newFrame.origin.y = max(origin.y, UIScreen.main.bounds.height - frame.height)
122-
return .just(newFrame)
123-
}
124-
125-
// merge into single sequence
126-
Observable.merge(didPan, willChangeFrame, willHide)
127-
.bind(to: frameVariable)
128-
.disposed(by: disposeBag)
129-
130-
// gesture recognizer
131-
panRecognizer.delegate = self
132-
133-
UIApplication.rx.didFinishLaunching // when RxKeyboard is initialized before UIApplication.window is created
134-
.withUnretained(panRecognizer)
135-
.subscribe { gestureRecognizer, _ in
136-
UIApplication.shared.windows.first?.addGestureRecognizer(gestureRecognizer)
137-
}
138-
.disposed(by: disposeBag)
139-
}
25+
// MARK: Public
26+
27+
/// Get a singleton instance.
28+
public static let instance = RxKeyboard()
29+
30+
/// An observable keyboard frame.
31+
public let frame: Driver<CGRect>
32+
33+
/// An observable visible height of keyboard. Emits keyboard height if the keyboard is visible
34+
/// or `0` if the keyboard is not visible.
35+
public let visibleHeight: Driver<CGFloat>
36+
37+
/// Same with `visibleHeight` but only emits values when keyboard is about to show. This is
38+
/// useful when adjusting scroll view content offset.
39+
public let willShowVisibleHeight: Driver<CGFloat>
40+
41+
/// An observable visibility of keyboard. Emits keyboard visibility
42+
/// when changed keyboard show and hide.
43+
public let isHidden: Driver<Bool>
44+
45+
// MARK: Private
46+
47+
private let disposeBag = DisposeBag()
48+
private let panRecognizer = UIPanGestureRecognizer()
49+
50+
// MARK: Initializing
51+
52+
override init() {
53+
54+
let keyboardWillChangeFrame = UIResponder.keyboardWillChangeFrameNotification
55+
let keyboardWillHide = UIResponder.keyboardWillHideNotification
56+
let keyboardFrameEndKey = UIResponder.keyboardFrameEndUserInfoKey
57+
58+
let defaultFrame = CGRect(
59+
x: 0,
60+
y: UIScreen.main.bounds.height,
61+
width: UIScreen.main.bounds.width,
62+
height: 0
63+
)
64+
let frameVariable = BehaviorRelay<CGRect>(value: defaultFrame)
65+
self.frame = frameVariable.asDriver().distinctUntilChanged()
66+
self.visibleHeight = self.frame.map { UIScreen.main.bounds.height - $0.origin.y }
67+
self.willShowVisibleHeight = self.visibleHeight
68+
.scan((visibleHeight: 0, isShowing: false)) { lastState, newVisibleHeight in
69+
return (visibleHeight: newVisibleHeight, isShowing: lastState.visibleHeight == 0 && newVisibleHeight > 0)
70+
}
71+
.filter { state in state.isShowing }
72+
.map { state in state.visibleHeight }
73+
self.isHidden = self.visibleHeight.map({ $0 == 0.0 }).distinctUntilChanged()
74+
super.init()
75+
76+
// keyboard will change frame
77+
let willChangeFrame = NotificationCenter.default.rx.notification(keyboardWillChangeFrame)
78+
.map { notification -> CGRect in
79+
let rectValue = notification.userInfo?[keyboardFrameEndKey] as? NSValue
80+
return rectValue?.cgRectValue ?? defaultFrame
81+
}
82+
.map { frame -> CGRect in
83+
if frame.origin.y < 0 { // if went to wrong frame
84+
var newFrame = frame
85+
newFrame.origin.y = UIScreen.main.bounds.height - newFrame.height
86+
return newFrame
87+
}
88+
return frame
89+
}
90+
91+
// keyboard will hide
92+
let willHide = NotificationCenter.default.rx.notification(keyboardWillHide)
93+
.map { notification -> CGRect in
94+
let rectValue = notification.userInfo?[keyboardFrameEndKey] as? NSValue
95+
return rectValue?.cgRectValue ?? defaultFrame
96+
}
97+
.map { frame -> CGRect in
98+
if frame.origin.y < 0 { // if went to wrong frame
99+
var newFrame = frame
100+
newFrame.origin.y = UIScreen.main.bounds.height
101+
return newFrame
102+
}
103+
return frame
104+
}
105+
106+
// pan gesture
107+
let didPan = self.panRecognizer.rx.event
108+
.withLatestFrom(frameVariable.asObservable()) { ($0, $1) }
109+
.flatMap { (gestureRecognizer, frame) -> Observable<CGRect> in
110+
guard case .changed = gestureRecognizer.state,
111+
let window = UIApplication.shared.windows.first,
112+
frame.origin.y < UIScreen.main.bounds.height
113+
else { return .empty() }
114+
let origin = gestureRecognizer.location(in: window)
115+
var newFrame = frame
116+
newFrame.origin.y = max(origin.y, UIScreen.main.bounds.height - frame.height)
117+
return .just(newFrame)
118+
}
119+
120+
// merge into single sequence
121+
Observable.of(didPan, willChangeFrame, willHide).merge()
122+
.bind(to: frameVariable)
123+
.disposed(by: self.disposeBag)
124+
125+
// gesture recognizer
126+
self.panRecognizer.delegate = self
127+
128+
UIApplication.rx.didFinishLaunching // when RxKeyboard is initialized before UIApplication.window is created
129+
.subscribe(onNext: { _ in
130+
UIApplication.shared.windows.first?.addGestureRecognizer(self.panRecognizer)
131+
})
132+
.disposed(by: self.disposeBag)
133+
}
134+
140135
}
141136

142137

143138
// MARK: - UIGestureRecognizerDelegate
144139

145140
extension RxKeyboard: UIGestureRecognizerDelegate {
146141

147-
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
148-
let point = touch.location(in: gestureRecognizer.view)
149-
var view = gestureRecognizer.view?.hitTest(point, with: nil)
150-
151-
while let candidate = view {
152-
if let scrollView = candidate as? UIScrollView,
153-
case .interactive = scrollView.keyboardDismissMode {
154-
return true
155-
}
156-
view = candidate.superview
157-
}
158-
159-
return false
142+
public func gestureRecognizer(
143+
_ gestureRecognizer: UIGestureRecognizer,
144+
shouldReceive touch: UITouch
145+
) -> Bool {
146+
let point = touch.location(in: gestureRecognizer.view)
147+
var view = gestureRecognizer.view?.hitTest(point, with: nil)
148+
while let candidate = view {
149+
if let scrollView = candidate as? UIScrollView,
150+
case .interactive = scrollView.keyboardDismissMode {
151+
return true
152+
}
153+
view = candidate.superview
160154
}
155+
return false
156+
}
161157

162-
public func gestureRecognizer(
163-
_ gestureRecognizer: UIGestureRecognizer,
164-
shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer
165-
) -> Bool {
166-
return gestureRecognizer === panRecognizer
167-
}
168-
}
169-
170-
private extension Notification.Name {
171-
172-
static let keyboardWillChangeFrame = UIResponder.keyboardWillChangeFrameNotification
173-
static let keyboardWillHide = UIResponder.keyboardWillHideNotification
174-
}
175-
176-
private extension String {
158+
public func gestureRecognizer(
159+
_ gestureRecognizer: UIGestureRecognizer,
160+
shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer
161+
) -> Bool {
162+
return gestureRecognizer === self.panRecognizer
163+
}
177164

178-
static let keyboardFrameEndKey = UIResponder.keyboardFrameEndUserInfoKey
179165
}
180-
181166
#endif
182167

0 commit comments

Comments
 (0)