diff --git a/CHANGELOG.md b/CHANGELOG.md index ed08715..8c25038 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,20 @@ # Change Log All notable changes to this project will be documented in this file. +## 9.0.6 + +### Features + +* Add `UIView` associated type to `Event`, e.g. `willShow(UIView)` so that event listeners can inspect the view. +* Add `Event.id: String?` property so that event listeners can reason about the view's ID. + +## 9.0.5 + +### Fixes + +* #482 Fix timing of `KeyboardTrackingView` callbacks. +* #483 KeyboardTrackingView causes a small space under bottom-style view + ## 9.0.4 * #471 Xcode 13 issue - Enum cases with associated values cannot be marked potentially unavailable with '@available' diff --git a/Package.swift b/Package.swift index 5324d1b..a0f30e8 100644 --- a/Package.swift +++ b/Package.swift @@ -7,7 +7,8 @@ let package = Package( .iOS("9.0") ], products: [ - .library(name: "SwiftMessages", targets: ["SwiftMessages"]) + .library(name: "SwiftMessages", targets: ["SwiftMessages"]), + .library(name: "SwiftMessages-Dynamic", type: .dynamic, targets: ["SwiftMessages"]) ], targets: [ .target( diff --git a/README.md b/README.md index c46c84c..97e8374 100644 --- a/README.md +++ b/README.md @@ -156,7 +156,9 @@ config.preferredStatusBarStyle = .lightContent // Specify one or more event listeners to respond to show and hide events. config.eventListeners.append() { event in - if case .didHide = event { print("yep") } + if case .didHide = event { + print("yep id=\(String(describing: event.id)") + } } SwiftMessages.show(config: config, view: view) diff --git a/SwiftMessages.podspec b/SwiftMessages.podspec index 688f100..4c7b945 100644 --- a/SwiftMessages.podspec +++ b/SwiftMessages.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'SwiftMessages' - spec.version = '9.0.4' + spec.version = '9.0.6' spec.license = { :type => 'MIT' } spec.homepage = 'https://github.com/SwiftKickMobile/SwiftMessages' spec.authors = { 'Timothy Moose' => 'tim@swiftkick.it' } diff --git a/SwiftMessages/KeyboardTrackingView.swift b/SwiftMessages/KeyboardTrackingView.swift index 6af384a..301d969 100644 --- a/SwiftMessages/KeyboardTrackingView.swift +++ b/SwiftMessages/KeyboardTrackingView.swift @@ -44,6 +44,18 @@ open class KeyboardTrackingView: UIView { /// The margin to maintain between the keyboard and the top of the view. @IBInspectable open var topMargin: CGFloat = 0 + /// Subclasses can override this to do something before the change. + open func willChange( + change: KeyboardTrackingView.Change, + userInfo: [AnyHashable : Any] + ) {} + + /// Subclasses can override this to do something after the change. + open func didChange( + change: KeyboardTrackingView.Change, + userInfo: [AnyHashable : Any] + ) {} + override public init(frame: CGRect) { super.init(frame: frame) postInit() @@ -101,11 +113,12 @@ open class KeyboardTrackingView: UIView { guard !(isPaused || isAutomaticallyPaused), let userInfo = (notification as NSNotification).userInfo, let value = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return } + willChange(change: change, userInfo: userInfo) + delegate?.keyboardTrackingViewWillChange(change: change, userInfo: userInfo) let keyboardRect = value.cgRectValue let thisRect = convert(bounds, to: nil) let newHeight = max(0, thisRect.maxY - keyboardRect.minY) + topMargin guard heightConstraint.constant != newHeight else { return } - delegate?.keyboardTrackingViewWillChange(change: change, userInfo: userInfo) animateKeyboardChange(change: change, height: newHeight, userInfo: userInfo) } @@ -115,6 +128,7 @@ open class KeyboardTrackingView: UIView { let curveNumber = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber { CATransaction.begin() CATransaction.setCompletionBlock { + self.didChange(change: change, userInfo: userInfo) self.delegate?.keyboardTrackingViewDidChange(change: change, userInfo: userInfo) } UIView.beginAnimations(nil, context: nil) diff --git a/SwiftMessages/MaskingView.swift b/SwiftMessages/MaskingView.swift index 0ce4c42..d631342 100644 --- a/SwiftMessages/MaskingView.swift +++ b/SwiftMessages/MaskingView.swift @@ -65,6 +65,15 @@ class MaskingView: PassthroughView { guard let keyboardTrackingView = keyboardTrackingView, view != keyboardTrackingView, view != backgroundView else { return } - keyboardTrackingView.topAnchor.constraint(greaterThanOrEqualTo: view.bottomAnchor).with(priority: UILayoutPriority(250)).isActive = true + let offset: CGFloat + if let adjustable = view as? MarginAdjustable { + offset = -adjustable.bounceAnimationOffset + } else { + offset = 0 + } + keyboardTrackingView.topAnchor.constraint( + greaterThanOrEqualTo: view.bottomAnchor, + constant: offset + ).with(priority: UILayoutPriority(250)).isActive = true } } diff --git a/SwiftMessages/Presenter.swift b/SwiftMessages/Presenter.swift index 11243f5..be093be 100644 --- a/SwiftMessages/Presenter.swift +++ b/SwiftMessages/Presenter.swift @@ -119,7 +119,7 @@ class Presenter: NSObject { func show(completion: @escaping AnimationCompletion) throws { try presentationContext = getPresentationContext() install() - self.config.eventListeners.forEach { $0(.willShow) } + self.config.eventListeners.forEach { $0(.willShow(self.view)) } showAnimation() { completed in completion(completed) if completed { @@ -128,7 +128,7 @@ class Presenter: NSObject { } else { self.showAccessibilityAnnouncement() } - self.config.eventListeners.forEach { $0(.didShow) } + self.config.eventListeners.forEach { $0(.didShow(self.view)) } } } } @@ -181,7 +181,7 @@ class Presenter: NSObject { func hide(animated: Bool, completion: @escaping AnimationCompletion) { isHiding = true - self.config.eventListeners.forEach { $0(.willHide) } + self.config.eventListeners.forEach { $0(.willHide(self.view)) } let context = animationContext() let action = { if let viewController = self.presentationContext.viewControllerValue() as? WindowViewController { @@ -189,7 +189,7 @@ class Presenter: NSObject { } self.maskingView.removeFromSuperview() completion(true) - self.config.eventListeners.forEach { $0(.didHide) } + self.config.eventListeners.forEach { $0(.didHide(self.view)) } } guard animated else { action() diff --git a/SwiftMessages/SwiftMessages.swift b/SwiftMessages/SwiftMessages.swift index 7c0042f..5e9f0c3 100644 --- a/SwiftMessages/SwiftMessages.swift +++ b/SwiftMessages/SwiftMessages.swift @@ -219,10 +219,23 @@ open class SwiftMessages { Specifies events in the message lifecycle. */ public enum Event { - case willShow - case didShow - case willHide - case didHide + case willShow(UIView) + case didShow(UIView) + case willHide(UIView) + case didHide(UIView) + + public var view: UIView { + switch self { + case .willShow(let view): return view + case .didShow(let view): return view + case .willHide(let view): return view + case .didHide(let view): return view + } + } + + public var id: String? { + return (view as? Identifiable)?.id + } } /** diff --git a/SwiftMessages/WindowViewController.swift b/SwiftMessages/WindowViewController.swift index 9c2b721..389ac77 100644 --- a/SwiftMessages/WindowViewController.swift +++ b/SwiftMessages/WindowViewController.swift @@ -28,7 +28,9 @@ open class WindowViewController: UIViewController window.rootViewController = self window.windowLevel = config.windowLevel ?? UIWindow.Level.normal if #available(iOS 13, *) { - window.overrideUserInterfaceStyle = config.overrideUserInterfaceStyle + if window.responds(to: #selector(setter: UIView.overrideUserInterfaceStyle)) { + window.setValue(config.overrideUserInterfaceStyle.rawValue, forKeyPath: #keyPath(UIView.overrideUserInterfaceStyle)) + } } }