Skip to content

Commit 69eff12

Browse files
authored
feat: iPad 환경에서 키보드 처리 지원 (#70)
* feat: 서로 다른 모서리에 각기 다른 CornerRadius 값을 줄 수 있도록 코드 구현 * fix: iPad 환경에서 키보드 처리가 제대로 되지 않는 문제 수정
1 parent 80c4f36 commit 69eff12

File tree

3 files changed

+77
-56
lines changed

3 files changed

+77
-56
lines changed

Example/TSAlertController.xcodeproj/project.pbxproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,9 +545,12 @@
545545
MODULE_NAME = ExampleApp;
546546
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
547547
PRODUCT_NAME = "$(TARGET_NAME)";
548+
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
549+
SUPPORTS_MACCATALYST = NO;
548550
SWIFT_STRICT_CONCURRENCY = minimal;
549551
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
550552
SWIFT_VERSION = 5.0;
553+
TARGETED_DEVICE_FAMILY = "1,2";
551554
};
552555
name = Debug;
553556
};
@@ -569,9 +572,12 @@
569572
MODULE_NAME = ExampleApp;
570573
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
571574
PRODUCT_NAME = "$(TARGET_NAME)";
575+
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
576+
SUPPORTS_MACCATALYST = NO;
572577
SWIFT_STRICT_CONCURRENCY = minimal;
573578
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
574579
SWIFT_VERSION = 5.0;
580+
TARGETED_DEVICE_FAMILY = "1,2";
575581
};
576582
name = Release;
577583
};

Example/Tests/TSAlertControllerTests.swift

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import XCTest
33

44
final class TSAlertControllerTests: XCTestCase {
55

6+
// MARK: - Verifies that TSAlertController initializes with correct title, message, and preferredStyle
7+
68
func testTSAlertController_WhenInitialized_ShouldSetTitleMessageAndPreferredStyle() {
79
// given
810
let alertController = TSAlertController(
@@ -22,6 +24,9 @@ final class TSAlertControllerTests: XCTestCase {
2224
XCTAssertEqual(mockViewController.presentViewControllerTarget, alertController)
2325
}
2426

27+
28+
// MARK: - Verifies that TSAlertController initializes with correct textfields
29+
2530
func testTSAlertController_WhenIntializedWithTextFields_ShouldSetTextFields() {
2631
// given
2732
let alertController = TSAlertController(
@@ -41,6 +46,10 @@ final class TSAlertControllerTests: XCTestCase {
4146
XCTAssertEqual(mockViewController.presentViewControllerTarget, alertController)
4247
}
4348

49+
50+
51+
// MARK: - Verifies that TSAlertController initializes with the correct actions order and count
52+
4453
func testTSAlertController_WhenInitializedWithTwoButtonsAndAutomaticAxis_ShouldSetCorrectActionsOrderAndCount() {
4554
// given
4655
let alertController = TSAlertController(
@@ -95,6 +104,9 @@ final class TSAlertControllerTests: XCTestCase {
95104
}
96105

97106

107+
108+
109+
98110
func testTSAlertController_WhenIntlaizedWithAlertStyle_ShouldSetDefaultConfiguration() {
99111
// given
100112
let alertController = TSAlertController(
@@ -205,12 +217,11 @@ final class TSAlertControllerTests: XCTestCase {
205217
// then
206218
let config = alertController.configuration
207219
XCTAssertFalse(alertController.options.contains(.stretchyDragging))
208-
XCTAssertEqual(config.prefersGrabberVisible, true)
209220
XCTAssertEqual(mockViewController.presentViewControllerTarget, alertController)
210221
XCTAssertEqual(mockViewController.presentViewControllerTarget, alertController)
211222
}
212223

213-
func testTSAlertController_WhenIntializedWithActionSheetStyle_ShouldSetDefaultCconfiguration() {
224+
func testTSAlertController_WhenIntializedWithActionSheetStyle_ShouldSetDefaultConfiguration() {
214225
// given
215226
let alertController = TSAlertController(
216227
title: "The title of the alert",
@@ -263,8 +274,26 @@ final class TSAlertControllerTests: XCTestCase {
263274
// then
264275
let config = alertController.configuration
265276
XCTAssertFalse(alertController.options.contains(.interactiveScaleAndDrag))
266-
XCTAssertEqual(config.prefersGrabberVisible, true)
267277
XCTAssertEqual(mockViewController.presentViewControllerTarget, alertController)
278+
}
279+
280+
func testTSAlertController_WhenIntializedWithActionSheetStyle_ShouldSetCorrectViewConfigurationForcibly() {
281+
// given
282+
let alertController = TSAlertController(
283+
title: "The title of the alert",
284+
preferredStyle: .actionSheet
285+
)
286+
let mockViewController = MockViewController()
287+
288+
// when
289+
alertController.viewConfiguration.cornerRadius = 25.0
290+
291+
mockViewController.present(alertController, animated: true)
292+
293+
// then
294+
let viewConfig = alertController.viewConfiguration
295+
XCTAssertEqual(viewConfig.cornerRadius.bottomLeft, 0.0)
296+
XCTAssertEqual(viewConfig.cornerRadius.bottomRight, 0.0)
268297
XCTAssertEqual(mockViewController.presentViewControllerTarget, alertController)
269298
}
270299

Sources/TSAlert/TSAlertController.swift

Lines changed: 39 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ public final class TSAlertController: UIViewController {
236236
public override func viewDidLayoutSubviews() {
237237
super.viewDidLayoutSubviews()
238238

239+
initialViewTopY = view.frame.origin.y
239240
view.applyRoundCorners(viewConfiguration.cornerRadius)
240241
}
241242

@@ -413,14 +414,12 @@ public final class TSAlertController: UIViewController {
413414

414415
// Registers notifications to handle keyboard appearance and disappearance.
415416
private func registerKeyboardNotifications() {
416-
NotificationCenter.default.addObserver(self,
417-
selector: #selector(keyboardWillShow(_:)),
418-
name: UIResponder.keyboardWillShowNotification,
419-
object: nil)
420-
NotificationCenter.default.addObserver(self,
421-
selector: #selector(keyboardWillHide(_:)),
422-
name: UIResponder.keyboardWillHideNotification,
423-
object: nil)
417+
NotificationCenter.default.addObserver(
418+
self,
419+
selector: #selector(keyboardWillChangeFrame(_:)),
420+
name: UIResponder.keyboardWillChangeFrameNotification,
421+
object: nil
422+
)
424423
}
425424

426425
// Registers notifications to handle keyboard appearance and disappearance.
@@ -691,7 +690,6 @@ private extension TSAlertController {
691690
}
692691
}
693692

694-
///
695693
@objc private func handleStretchyDragging(_ gesture: UIPanGestureRecognizer) {
696694

697695
let interpolationFactor: CGFloat = 0.025
@@ -729,57 +727,45 @@ private extension TSAlertController {
729727

730728
private extension TSAlertController {
731729

732-
// Adjusts the alert’s position when the keyboard appears.
733-
@objc func keyboardWillShow(_ notification: Notification) {
734-
// If this method is not blocked, the alert view's position may animate incorrectly
735-
// when the keyboard suggestion bar appears or disappears.
736-
guard !isKeyboardShown else { return }
730+
@objc func keyboardWillChangeFrame(_ notification: Notification) {
737731

738732
guard let userInfo = notification.userInfo,
739733
let keyboardFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect,
740-
let keyboardAnimationDuration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber else {
741-
return
742-
}
743-
744-
let viewHeight = view.frame.height
745-
let keyboardTopY = keyboardFrame.origin.y
746-
747-
let duration = keyboardAnimationDuration.doubleValue
748-
let adjustedViewTopY = keyboardTopY - viewConfiguration.spacing.keyboardSpacing - viewHeight
749-
750-
// Move the alert up only if the spacing is smaller than the configured value.
751-
// If the space between the alert and the keyboard is greater than the configured value, the alert will not move.
752-
if adjustedViewTopY < initialViewTopY {
753-
UIView.animate(withDuration: duration,
754-
delay: 0,
755-
options: .curveEaseIn) {
756-
self.view.frame.origin.y = adjustedViewTopY
757-
}
758-
}
734+
let keyboardAnimationDuration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber
735+
else { return }
759736

760-
isKeyboardShown = true
761-
}
762-
763-
// Resets the alert’s position when the keyboard disappears.
764-
@objc func keyboardWillHide(_ notification: Notification) {
765-
// If this method is not blocked, the alert view's position may animate incorrectly
766-
// when the keyboard suggestion bar appears or disappears.
767-
guard isKeyboardShown else { return }
737+
let alertViewHeight = view.frame.height // Alert 뷰의 전체 높이
738+
let keyboardOriginY = keyboardFrame.origin.y // 상위 뷰 기준, 키보드의 상단 y 좌표
768739

769-
guard let userInfo = notification.userInfo,
770-
let keyboardAnimationDuration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber else {
771-
return
772-
}
773740
let duration = keyboardAnimationDuration.doubleValue
774-
775-
// Ensure the software keyboard is enabled for proper testing (Command + K).
776-
UIView.animate(withDuration: duration,
777-
delay: 0,
778-
options: .curveEaseIn) {
779-
self.view.frame.origin.y = self.initialViewTopY
741+
let adjustedViewTopY = keyboardOriginY - viewConfiguration.spacing.keyboardSpacing - alertViewHeight
742+
// 키보드 상단 y 좌표에서 지정된 간격(keyboardSpacing)을 뺀 뒤,
743+
// Alert 뷰의 전체 높이를 빼면 Alert 뷰의 새로운 y 좌표를 구할 수 있음
744+
745+
// 키보드가 나타난 상태일 때 실행
746+
if isKeyboardShown {
747+
UIView.animate(
748+
withDuration: duration,
749+
delay: 0,
750+
options: .curveEaseIn
751+
) {
752+
self.view.frame.origin.y = self.initialViewTopY
753+
} completion: { _ in
754+
self.isKeyboardShown = false
755+
}
756+
} else if adjustedViewTopY < initialViewTopY && !isKeyboardShown {
757+
// Move the alert up only if the spacing is smaller than the configured value.
758+
// If the space between the alert and the keyboard is greater than the configured value, the alert will not move.
759+
UIView.animate(
760+
withDuration: duration,
761+
delay: 0,
762+
options: .curveEaseIn
763+
) {
764+
self.view.frame.origin.y = adjustedViewTopY
765+
} completion: { _ in
766+
self.isKeyboardShown = true
767+
}
780768
}
781-
782-
isKeyboardShown = false
783769
}
784770
}
785771

0 commit comments

Comments
 (0)