Skip to content

Commit 360230b

Browse files
authored
fix: KeyboardExtender on iOS 26 with round corners (#1067)
## 📜 Description Added rounded corners to `KeyboardExtender` on iOS 26 to match Apple guidelines. ## 💡 Motivation and Context We need to specify `cornerConfiguration` property. By default in first OS versions it always had rounded corners, but in beta 5 it has rectangle corners again. The biggest issue was in the fact on how to add it and don't break compilation for older XCode versions. Before I used `NSClassFromString`, but since we need to use setter for that (and we need to set structure, not primitive values) this approach can not be easily utilized. Even if we'll use `respondTo` - the application will crash telling that selector is not exposed in objc 🤷‍♂️ Moreover this approach (with dynamic class lookup) is bad, because if the app was compiled on XCode 16.4 but is running on iOS 18, then `KeyboardExtender` will not be visible at all - we'll try to use unexisting class and will not create a view, but since base class is `UIInputView` we'll get something like this: <img width="300" height="655" alt="image" src="https://github.com/user-attachments/assets/2c2656b7-9812-44c9-b118-7f2d4d44448c" /> The other idea that I had was detecting xcode version during pod installation. White it works it also not a very bulletproof solution, because if you had two XCode on your laptop, then you can install it with XCode 26, but compilation with XCode 16 will fail. The most safe approach is to use `canImport` directive - this is what I used in this PR. I also wrapped a logic with container selection, to prevent the issue with incompatibility (i. e. compiled with XCode 16 running on iOS 26). ## 📢 Changelog <!-- High level overview of important changes --> <!-- For example: fixed status bar manipulation; added new types declarations; --> <!-- If your changes don't affect one of platform/language below - then remove this platform/language --> ### iOS - wrap in `#if canImport(UIKit.UIGlassEffect)` the `UIGlassEffect` usage. ## 🤔 How Has This Been Tested? Tested manually on iPhone 16 Pro (iOS 26.0, 18.5). ## 📸 Screenshots (if appropriate): |Before|After| |-------|-----| |<img width="603" height="1311" alt="Screenshot 2025-08-07 at 10 21 06" src="https://github.com/user-attachments/assets/c89b11dc-cec9-4b2e-879a-5fd6c247d32d" />|<img width="603" height="1311" alt="Screenshot 2025-08-07 at 10 19 30" src="https://github.com/user-attachments/assets/6c08e358-c574-4679-83a8-0331113bc044" />| ## 📝 Checklist - [x] CI successfully passed - [x] I added new mocks and corresponding unit-tests if library API was changed
1 parent af6d19d commit 360230b

2 files changed

Lines changed: 25 additions & 20 deletions

File tree

cspell.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
"CPLUSPLUSFLAGS",
102102
"xcconfig",
103103
"DKEYBOARD",
104+
"DUSES",
104105
"DRCT",
105106
"DFOLLY",
106107
"upto",

ios/views/KeyboardExtenderContainerView.swift

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ import UIKit
1010
@objc
1111
public class KeyboardExtenderContainerView: NSObject {
1212
@objc public static func create(frame: CGRect, contentView: UIView) -> UIView {
13-
if #available(iOS 26.0, *) {
14-
return ModernContainerView(frame: frame, contentView: contentView)
15-
} else {
16-
return LegacyContainerView(frame: frame, contentView: contentView)
17-
}
13+
#if canImport(UIKit.UIGlassEffect)
14+
if #available(iOS 26.0, *) {
15+
return ModernContainerView(frame: frame, contentView: contentView)
16+
}
17+
#endif
18+
19+
return LegacyContainerView(frame: frame, contentView: contentView)
1820
}
1921
}
2022

@@ -86,21 +88,23 @@ private class ModernContainerView: BaseContainerView {
8688
}
8789

8890
private func setupVisualEffect() {
89-
guard let glassEffectClass = NSClassFromString("UIGlassEffect") as? UIVisualEffect.Type else { return }
90-
91-
let isDark = FocusedInputHolder.shared.get()?.keyboardAppearanceValue == "dark"
92-
let glassEffect = glassEffectClass.init()
93-
let color = isDark ? UIColor.black.withAlphaComponent(0.3) : UIColor.gray.withAlphaComponent(0.3)
94-
glassEffect.setValue(color, forKey: "tintColor")
95-
glassEffect.setValue(true, forKey: "interactive")
96-
97-
visualEffectView = UIVisualEffectView(effect: glassEffect)
98-
visualEffectView?.overrideUserInterfaceStyle = isDark ? .dark : .light
99-
100-
if let visualEffectView = visualEffectView {
101-
visualEffectView.contentView.addSubview(contentView)
102-
addSubview(visualEffectView)
103-
}
91+
#if canImport(UIKit.UIGlassEffect)
92+
let isDark = FocusedInputHolder.shared.get()?.keyboardAppearanceValue == "dark"
93+
let glassEffect = UIGlassEffect()
94+
let color =
95+
isDark ? UIColor.black.withAlphaComponent(0.3) : UIColor.gray.withAlphaComponent(0.3)
96+
glassEffect.tintColor = color
97+
glassEffect.isInteractive = true
98+
99+
visualEffectView = UIVisualEffectView(effect: glassEffect)
100+
visualEffectView?.overrideUserInterfaceStyle = isDark ? .dark : .light
101+
visualEffectView?.cornerConfiguration = .capsule()
102+
103+
if let visualEffectView = visualEffectView {
104+
visualEffectView.contentView.addSubview(contentView)
105+
addSubview(visualEffectView)
106+
}
107+
#endif
104108
}
105109

106110
override func updateContentFrame(desiredHeight: CGFloat) {

0 commit comments

Comments
 (0)