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

View File

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

View File

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