Skip to content

Commit 53ddce0

Browse files
authored
Merge pull request #2248 from woocommerce/issue/2173-kfo-struct-to-class
Convert KeyboardFrameObserver to class
2 parents 223b6a6 + 94fec86 commit 53ddce0

File tree

2 files changed

+42
-20
lines changed

2 files changed

+42
-20
lines changed

WooCommerce/Classes/ViewRelated/Keyboard/KeyboardFrameObserver.swift

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import UIKit
22

33
/// Observes the keyboard frame and notifies its subscriber.
4-
struct KeyboardFrameObserver {
4+
final class KeyboardFrameObserver {
55
private let onKeyboardFrameUpdate: OnKeyboardFrameUpdate
66

77
/// Provides the last known keyboard state.
@@ -36,19 +36,16 @@ struct KeyboardFrameObserver {
3636
///
3737
/// - Parameter sendInitialEvent: If true, the subscriber will be immediately notified
3838
/// using the last known keyboard frame.
39-
mutating func startObservingKeyboardFrame(sendInitialEvent: Bool = false) {
40-
var observer = self
41-
notificationCenter.addObserver(forName: UIResponder.keyboardWillShowNotification,
42-
object: nil,
43-
queue: nil) { notification in
44-
observer.keyboardWillShow(notification)
45-
}
39+
func startObservingKeyboardFrame(sendInitialEvent: Bool = false) {
40+
notificationCenter.addObserver(self,
41+
selector: #selector(keyboardWillShow(_:)),
42+
name: UIResponder.keyboardWillShowNotification,
43+
object: nil)
4644

47-
notificationCenter.addObserver(forName: UIResponder.keyboardWillHideNotification,
48-
object: nil,
49-
queue: nil) { notification in
50-
observer.keyboardWillHide(notification)
51-
}
45+
notificationCenter.addObserver(self,
46+
selector: #selector(keyboardWillHide(_:)),
47+
name: UIResponder.keyboardWillHideNotification,
48+
object: nil)
5249

5350
if sendInitialEvent {
5451
keyboardFrame = keyboardStateProvider.state.frameEnd
@@ -57,14 +54,14 @@ struct KeyboardFrameObserver {
5754
}
5855

5956
private extension KeyboardFrameObserver {
60-
mutating func keyboardWillShow(_ notification: Foundation.Notification) {
57+
@objc func keyboardWillShow(_ notification: Foundation.Notification) {
6158
guard let keyboardFrame = keyboardRect(from: notification) else {
6259
return
6360
}
6461
self.keyboardFrame = keyboardFrame
6562
}
6663

67-
mutating func keyboardWillHide(_ notification: Foundation.Notification) {
64+
@objc func keyboardWillHide(_ notification: Foundation.Notification) {
6865
self.keyboardFrame = .zero
6966
}
7067
}

WooCommerce/WooCommerceTests/ViewRelated/Keyboard/KeyboardFrameObserverTests.swift

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ final class KeyboardFrameObserverTests: XCTestCase {
1616

1717
var actualFrames = [CGRect]()
1818

19-
var keyboardFrameObserver = KeyboardFrameObserver(notificationCenter: notificationCenter) { (keyboardFrame: CGRect) in
19+
let keyboardFrameObserver = KeyboardFrameObserver(notificationCenter: notificationCenter) { (keyboardFrame: CGRect) in
2020
actualFrames.append(keyboardFrame)
2121
if actualFrames.count >= expectedFrames.count {
2222
XCTAssertEqual(actualFrames, expectedFrames)
@@ -47,7 +47,7 @@ final class KeyboardFrameObserverTests: XCTestCase {
4747

4848
var actualFrames = [CGRect]()
4949

50-
var keyboardFrameObserver = KeyboardFrameObserver(notificationCenter: notificationCenter) { (keyboardFrame: CGRect) in
50+
let keyboardFrameObserver = KeyboardFrameObserver(notificationCenter: notificationCenter) { (keyboardFrame: CGRect) in
5151
actualFrames.append(keyboardFrame)
5252
if actualFrames.count >= expectedFrames.count {
5353
XCTAssertEqual(actualFrames, expectedFrames)
@@ -70,7 +70,7 @@ final class KeyboardFrameObserverTests: XCTestCase {
7070

7171
let expectationForKeyboardFrame = expectation(description: "Wait for keyboard frame updates")
7272

73-
var keyboardFrameObserver = KeyboardFrameObserver(notificationCenter: notificationCenter) { (keyboardFrame: CGRect) in
73+
let keyboardFrameObserver = KeyboardFrameObserver(notificationCenter: notificationCenter) { (keyboardFrame: CGRect) in
7474
expectationForKeyboardFrame.fulfill()
7575
}
7676
keyboardFrameObserver.startObservingKeyboardFrame()
@@ -88,7 +88,7 @@ final class KeyboardFrameObserverTests: XCTestCase {
8888

8989
let expectationForKeyboardFrame = expectation(description: "Wait for keyboard frame updates")
9090

91-
var keyboardFrameObserver = KeyboardFrameObserver(notificationCenter: notificationCenter) { (keyboardFrame: CGRect) in
91+
let keyboardFrameObserver = KeyboardFrameObserver(notificationCenter: notificationCenter) { (keyboardFrame: CGRect) in
9292
expectationForKeyboardFrame.fulfill()
9393
}
9494
keyboardFrameObserver.startObservingKeyboardFrame()
@@ -101,6 +101,31 @@ final class KeyboardFrameObserverTests: XCTestCase {
101101
waitForExpectations(timeout: 0.1)
102102
}
103103

104+
func testItWillNotEmitNewEventsWhenItIsDeallocated() {
105+
// Arrange
106+
let notificationCenter = NotificationCenter()
107+
108+
var eventsLogged = 0
109+
var keyboardFrameObserver: KeyboardFrameObserver? = KeyboardFrameObserver(notificationCenter: notificationCenter) { _ in
110+
eventsLogged += 1
111+
}
112+
113+
keyboardFrameObserver?.startObservingKeyboardFrame()
114+
115+
// These should be logged
116+
notificationCenter.postKeyboardWillShowNotification(keyboardFrame: CGRect(x: 1, y: 1, width: 1, height: 1))
117+
notificationCenter.postKeyboardWillShowNotification(keyboardFrame: CGRect(x: 2, y: 2, width: 2, height: 2))
118+
119+
// Act
120+
keyboardFrameObserver = nil
121+
122+
// This should not be logged anymore
123+
notificationCenter.postKeyboardWillShowNotification(keyboardFrame: CGRect(x: 3, y: 3, width: 3, height: 3))
124+
125+
// Assert
126+
XCTAssertEqual(eventsLogged, 2)
127+
}
128+
104129
func testItCanSendInitialEvents() {
105130
// Arrange
106131
let expectedKeyboardState = KeyboardState(
@@ -110,7 +135,7 @@ final class KeyboardFrameObserverTests: XCTestCase {
110135
let keyboardStateProvider = MockKeyboardStateProvider(state: expectedKeyboardState)
111136

112137
var actualKeyboardFrame: CGRect = .zero
113-
var keyboardFrameObserver = KeyboardFrameObserver(keyboardStateProvider: keyboardStateProvider) { frame in
138+
let keyboardFrameObserver = KeyboardFrameObserver(keyboardStateProvider: keyboardStateProvider) { frame in
114139
actualKeyboardFrame = frame
115140
}
116141

0 commit comments

Comments
 (0)