Skip to content

Commit 7d775a2

Browse files
authored
Fix tvOS CI (#224)
* Add set -e * Mark WebView as unavailable on tvOS * Fix compilation on tvOS * Fix isEditable didSet for accessibility
1 parent cc73562 commit 7d775a2

File tree

5 files changed

+100
-77
lines changed

5 files changed

+100
-77
lines changed

.github/workflows/build-test-and-docs.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,14 @@ jobs:
8080

8181
- name: Build
8282
run: |
83-
set -uexo pipefail
83+
set -uxo pipefail
8484
device_type=${{ matrix.device-type }}
8585
set +e
8686
deviceid=$(xcrun simctl list devices $device_type available | grep -v -- -- | tail -n 1 | grep -oE '[0-9A-F\-]{36}')
8787
if [ $? -eq 0 ]; then
8888
(
89+
set -e
90+
8991
buildtarget () {
9092
# Use the same derived data path as DocC compilation so that we don't duplicate work.
9193
xcodebuild -derivedDataPath /tmp/data -skipMacroValidation -scheme "$1" -destination "id=$deviceid" build | xcbeautify --renderer github-actions
@@ -116,6 +118,7 @@ jobs:
116118
)
117119
else
118120
echo "No $device_type simulators found" >&2
121+
false
119122
fi
120123
121124
- name: Extract UIKitBackend symbol graphs

Examples/Package.resolved

Lines changed: 7 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Sources/SwiftCrossUI/Views/WebView.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Foundation
22

3+
@available(tvOS, unavailable)
34
public struct WebView: ElementaryView {
45
@State var currentURL: URL?
56
@Binding var url: URL

Sources/UIKitBackend/UIKitBackend+Control.swift

Lines changed: 53 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,17 @@ final class TextFieldWidget: WrapperWidget<UITextField>, UITextFieldDelegate {
5959

6060
final class TextEditorWidget: WrapperWidget<UITextView>, UITextViewDelegate {
6161
var onChange: ((String) -> Void)?
62+
var isEditable: Bool = true {
63+
didSet {
64+
#if os(tvOS)
65+
if !isEditable {
66+
child.resignFirstResponder()
67+
}
68+
#else
69+
child.isEditable = isEditable
70+
#endif
71+
}
72+
}
6273

6374
init() {
6475
super.init(child: UITextView())
@@ -68,6 +79,10 @@ final class TextEditorWidget: WrapperWidget<UITextView>, UITextViewDelegate {
6879
func textViewDidChange(_: UITextView) {
6980
onChange?(child.text ?? "")
7081
}
82+
83+
func textViewShouldBeginEditing(_: UITextView) -> Bool {
84+
return isEditable
85+
}
7186
}
7287

7388
#if os(tvOS)
@@ -172,32 +187,36 @@ final class TappableWidget: ContainerWidget {
172187

173188
@available(tvOS, unavailable)
174189
final class HoverableWidget: ContainerWidget {
175-
private var hoverGestureRecognizer: UIHoverGestureRecognizer?
176-
177-
var hoverChangesHandler: ((Bool) -> Void)? {
178-
didSet {
179-
if hoverChangesHandler != nil && hoverGestureRecognizer == nil {
180-
let gestureRecognizer = UIHoverGestureRecognizer(
181-
target: self,
182-
action: #selector(hoveringChanged(_:)))
183-
child.view.addGestureRecognizer(gestureRecognizer)
184-
self.hoverGestureRecognizer = gestureRecognizer
185-
} else if hoverChangesHandler == nil, let hoverGestureRecognizer {
186-
child.view.removeGestureRecognizer(hoverGestureRecognizer)
187-
self.hoverGestureRecognizer = nil
190+
// So much as attempting to reference UIHoverGestureRecognizer here results in a linker error on tvOS.
191+
#if !os(tvOS)
192+
private var hoverGestureRecognizer: UIHoverGestureRecognizer?
193+
194+
var hoverChangesHandler: ((Bool) -> Void)? {
195+
didSet {
196+
if hoverChangesHandler != nil && hoverGestureRecognizer == nil {
197+
let gestureRecognizer = UIHoverGestureRecognizer(
198+
target: self,
199+
action: #selector(hoveringChanged(_:)))
200+
child.view.addGestureRecognizer(gestureRecognizer)
201+
self.hoverGestureRecognizer = gestureRecognizer
202+
} else if hoverChangesHandler == nil, let hoverGestureRecognizer {
203+
child.view.removeGestureRecognizer(hoverGestureRecognizer)
204+
self.hoverGestureRecognizer = nil
205+
}
188206
}
189207
}
190-
}
191208

192-
@objc
193-
func hoveringChanged(_ recognizer: UIHoverGestureRecognizer) {
194-
switch recognizer.state {
195-
case .began: hoverChangesHandler?(true)
196-
case .ended: hoverChangesHandler?(false)
197-
default: break
209+
@objc
210+
func hoveringChanged(_ recognizer: UIHoverGestureRecognizer) {
211+
switch recognizer.state {
212+
case .began: hoverChangesHandler?(true)
213+
case .ended: hoverChangesHandler?(false)
214+
default: break
215+
}
198216
}
199-
}
217+
#endif
200218
}
219+
201220
@available(tvOS, unavailable)
202221
final class SliderWidget: WrapperWidget<UISlider> {
203222
var onChange: ((Double) -> Void)?
@@ -332,7 +351,7 @@ extension UIKitBackend {
332351
) {
333352
let textEditorWidget = textEditor as! TextEditorWidget
334353

335-
textEditorWidget.child.isEditable = environment.isEnabled
354+
textEditorWidget.isEditable = environment.isEnabled
336355
textEditorWidget.child.font = environment.resolvedFont.uiFont
337356
textEditorWidget.child.textColor = UIColor(color: environment.suggestedForegroundColor)
338357
textEditorWidget.onChange = onChange
@@ -448,20 +467,20 @@ extension UIKitBackend {
448467
}
449468
}
450469

451-
public func createHoverTarget(wrapping child: Widget) -> Widget {
452-
HoverableWidget(child: child)
453-
}
470+
#if os(iOS) || os(visionOS) || targetEnvironment(macCatalyst)
471+
public func createHoverTarget(wrapping child: Widget) -> Widget {
472+
HoverableWidget(child: child)
473+
}
454474

455-
public func updateHoverTarget(
456-
_ hoverTarget: any WidgetProtocol,
457-
environment: EnvironmentValues,
458-
action: @escaping (Bool) -> Void
459-
) {
460-
let wrapper = hoverTarget as! HoverableWidget
461-
wrapper.hoverChangesHandler = action
462-
}
475+
public func updateHoverTarget(
476+
_ hoverTarget: any WidgetProtocol,
477+
environment: EnvironmentValues,
478+
action: @escaping (Bool) -> Void
479+
) {
480+
let wrapper = hoverTarget as! HoverableWidget
481+
wrapper.hoverChangesHandler = action
482+
}
463483

464-
#if os(iOS) || os(visionOS) || targetEnvironment(macCatalyst)
465484
public func createSlider() -> Widget {
466485
SliderWidget()
467486
}
Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,45 @@
1-
import SwiftCrossUI
2-
import WebKit
1+
#if !os(tvOS)
2+
import SwiftCrossUI
3+
import WebKit
34

4-
extension UIKitBackend {
5-
public func createWebView() -> Widget {
6-
WebViewWidget()
7-
}
5+
extension UIKitBackend {
6+
public func createWebView() -> Widget {
7+
WebViewWidget()
8+
}
89

9-
public func updateWebView(
10-
_ webView: Widget,
11-
environment: EnvironmentValues,
12-
onNavigate: @escaping (URL) -> Void
13-
) {
14-
let webView = webView as! WebViewWidget
15-
webView.onNavigate = onNavigate
16-
}
10+
public func updateWebView(
11+
_ webView: Widget,
12+
environment: EnvironmentValues,
13+
onNavigate: @escaping (URL) -> Void
14+
) {
15+
let webView = webView as! WebViewWidget
16+
webView.onNavigate = onNavigate
17+
}
1718

18-
public func navigateWebView(_ webView: Widget, to url: URL) {
19-
let webView = webView as! WebViewWidget
20-
let request = URLRequest(url: url)
21-
webView.child.load(request)
19+
public func navigateWebView(_ webView: Widget, to url: URL) {
20+
let webView = webView as! WebViewWidget
21+
let request = URLRequest(url: url)
22+
webView.child.load(request)
23+
}
2224
}
23-
}
2425

25-
/// A wrapper for WKWebView. Acts as the web view's delegate as well.
26-
final class WebViewWidget: WrapperWidget<WKWebView>, WKNavigationDelegate {
27-
var onNavigate: ((URL) -> Void)?
26+
/// A wrapper for WKWebView. Acts as the web view's delegate as well.
27+
final class WebViewWidget: WrapperWidget<WKWebView>, WKNavigationDelegate {
28+
var onNavigate: ((URL) -> Void)?
2829

29-
init() {
30-
super.init(child: WKWebView())
30+
init() {
31+
super.init(child: WKWebView())
3132

32-
child.navigationDelegate = self
33-
}
34-
35-
func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
36-
guard let url = webView.url else {
37-
print("warning: Web view has no URL")
38-
return
33+
child.navigationDelegate = self
3934
}
4035

41-
onNavigate?(url)
36+
func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
37+
guard let url = webView.url else {
38+
print("warning: Web view has no URL")
39+
return
40+
}
41+
42+
onNavigate?(url)
43+
}
4244
}
43-
}
45+
#endif

0 commit comments

Comments
 (0)