Created
December 4, 2023 07:28
-
-
Save lukaskubanek/57d0faea1de51728ceb3196667d7810f to your computer and use it in GitHub Desktop.
A patch for SwiftUI views that disables keyboard avoidance
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import InterposeKit | |
import UIKit | |
import SwiftUI | |
import SwiftUIIntrospect | |
extension View { | |
public func keyboardAvoidanceDisabled() -> some View { | |
self.introspect(.viewController, on: .iOS(.v17)) { viewController in | |
if let hostingView = viewController.parent?.view { | |
if String(describing: type(of: hostingView)).hasPrefix("_UIHostingView") { | |
hostingView.installPatchForDisablingKeyboardAvoidanceIfNeeded() | |
} | |
} | |
} | |
} | |
} | |
// https://steipete.com/posts/disabling-keyboard-avoidance-in-swiftui-uihostingcontroller/ | |
extension UIView { | |
fileprivate func installPatchForDisablingKeyboardAvoidanceIfNeeded() { | |
guard !self.isKeyboardAvoidanceDisablingPatchInstalled else { return } | |
defer { self.isKeyboardAvoidanceDisablingPatchInstalled = true } | |
do { | |
try self.hook( | |
Selector(("keyboardWillShowWithNotification:")), | |
methodSignature: (@convention(c) (UIView, Selector, Notification) -> Void).self, | |
hookSignature: (@convention(block) (UIView, Notification) -> Void).self | |
) { hook in | |
return { _, _ in /* noop */ } | |
} | |
try self.hook( | |
Selector(("keyboardWillHideWithNotification:")), | |
methodSignature: (@convention(c) (UIView, Selector, Notification) -> Void).self, | |
hookSignature: (@convention(block) (UIView, Notification) -> Void).self | |
) { hook in | |
return { _, _ in /* noop */ } | |
} | |
} catch { | |
assertionFailure( | |
""" | |
\(UIView.self): Failed applying patch for disabling keyboard avoidance. | |
""" | |
) | |
} | |
} | |
} | |
extension UIView { | |
fileprivate var isKeyboardAvoidanceDisablingPatchInstalled: Bool { | |
get { self.getAssociatedObject(forKey: .isKeyboardAvoidanceDisablingPatchInstalled, default: false) } | |
set { self.setAssociatedObject(newValue, forKey: .isKeyboardAvoidanceDisablingPatchInstalled) } | |
} | |
} | |
extension AssociationKeys { | |
fileprivate static let isKeyboardAvoidanceDisablingPatchInstalled = AssociationKey<Bool>() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment