fix: tighten iOS main-actor handling

This commit is contained in:
Peter Steinberger
2025-12-20 01:48:14 +01:00
parent 1b38ee8b46
commit b2e11c504b
3 changed files with 15 additions and 13 deletions

View File

@@ -294,13 +294,14 @@ extension Double {
// MARK: - Navigation Delegate // MARK: - Navigation Delegate
/// Handles navigation policy to intercept clawdis:// deep links from canvas /// Handles navigation policy to intercept clawdis:// deep links from canvas
@MainActor
private final class ScreenNavigationDelegate: NSObject, WKNavigationDelegate { private final class ScreenNavigationDelegate: NSObject, WKNavigationDelegate {
weak var controller: ScreenController? weak var controller: ScreenController?
func webView( func webView(
_ webView: WKWebView, _ webView: WKWebView,
decidePolicyFor navigationAction: WKNavigationAction, decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) decisionHandler: @escaping @MainActor @Sendable (WKNavigationActionPolicy) -> Void)
{ {
guard let url = navigationAction.request.url else { guard let url = navigationAction.request.url else {
decisionHandler(.allow) decisionHandler(.allow)
@@ -310,9 +311,7 @@ private final class ScreenNavigationDelegate: NSObject, WKNavigationDelegate {
// Intercept clawdis:// deep links // Intercept clawdis:// deep links
if url.scheme == "clawdis" { if url.scheme == "clawdis" {
decisionHandler(.cancel) decisionHandler(.cancel)
Task { @MainActor in self.controller?.onDeepLink?(url)
self.controller?.onDeepLink?(url)
}
return return
} }
@@ -324,15 +323,11 @@ private final class ScreenNavigationDelegate: NSObject, WKNavigationDelegate {
didFailProvisionalNavigation _: WKNavigation?, didFailProvisionalNavigation _: WKNavigation?,
withError error: any Error) withError error: any Error)
{ {
Task { @MainActor in self.controller?.errorText = error.localizedDescription
self.controller?.errorText = error.localizedDescription
}
} }
func webView(_: WKWebView, didFail _: WKNavigation?, withError error: any Error) { func webView(_: WKWebView, didFail _: WKNavigation?, withError error: any Error) {
Task { @MainActor in self.controller?.errorText = error.localizedDescription
self.controller?.errorText = error.localizedDescription
}
} }
} }

View File

@@ -3,6 +3,10 @@ import ReplayKit
@MainActor @MainActor
final class ScreenRecordService { final class ScreenRecordService {
private struct UncheckedSendableBox<T>: @unchecked Sendable {
let value: T
}
enum ScreenRecordError: LocalizedError { enum ScreenRecordError: LocalizedError {
case invalidScreenIndex(Int) case invalidScreenIndex(Int)
case captureFailed(String) case captureFailed(String)
@@ -20,6 +24,7 @@ final class ScreenRecordService {
} }
} }
// swiftlint:disable:next cyclomatic_complexity
func record( func record(
screenIndex: Int?, screenIndex: Int?,
durationMs: Int?, durationMs: Int?,
@@ -165,8 +170,10 @@ final class ScreenRecordService {
videoInput.markAsFinished() videoInput.markAsFinished()
audioInput?.markAsFinished() audioInput?.markAsFinished()
let writerBox = UncheckedSendableBox(value: writer)
try await withCheckedThrowingContinuation { (cont: CheckedContinuation<Void, Error>) in try await withCheckedThrowingContinuation { (cont: CheckedContinuation<Void, Error>) in
writer.finishWriting { writerBox.value.finishWriting {
let writer = writerBox.value
if let err = writer.error { if let err = writer.error {
cont.resume(throwing: ScreenRecordError.writeFailed(err.localizedDescription)) cont.resume(throwing: ScreenRecordError.writeFailed(err.localizedDescription))
} else if writer.status != .completed { } else if writer.status != .completed {

View File

@@ -94,7 +94,7 @@ final class VoiceWakeManager: NSObject {
private var lastDispatched: String? private var lastDispatched: String?
private var onCommand: (@Sendable (String) async -> Void)? private var onCommand: (@Sendable (String) async -> Void)?
private nonisolated(unsafe) var userDefaultsObserver: NSObjectProtocol? private var userDefaultsObserver: NSObjectProtocol?
override init() { override init() {
super.init() super.init()
@@ -110,7 +110,7 @@ final class VoiceWakeManager: NSObject {
}) })
} }
deinit { @MainActor deinit {
if let userDefaultsObserver = self.userDefaultsObserver { if let userDefaultsObserver = self.userDefaultsObserver {
NotificationCenter.default.removeObserver(userDefaultsObserver) NotificationCenter.default.removeObserver(userDefaultsObserver)
} }