Fix a crash on macOS when using QuickLook. (#5790)

Introduced by the default @MainActor isolation and macOS being weird with threads.
This commit is contained in:
Doug
2026-06-24 18:34:45 +01:00
committed by GitHub
parent 3c5c1c62e3
commit 605ccc6be7
4 changed files with 29 additions and 15 deletions
@@ -153,11 +153,11 @@ private struct MediaPreviewViewController: UIViewControllerRepresentable {
class MediaPreviewItem: NSObject, QLPreviewItem {
let file: MediaFileHandleProxy
var previewItemURL: URL? {
nonisolated var previewItemURL: URL? { // nonisolated as QuickLook can call from any thread (macOS 26).
file.url
}
let previewItemTitle: String?
nonisolated let previewItemTitle: String? // nonisolated as QuickLook can call from any thread (macOS 26).
init(file: MediaFileHandleProxy, title: String?) {
self.file = file
@@ -9,6 +9,7 @@
import Combine
import Foundation
import QuickLook
import Synchronization
/// A dedicated data source for QLPreviewController to support timeline updates. This was added to
/// workaround the fact that calling `reloadData` on the controller **always** reloads the current
@@ -147,8 +148,14 @@ enum TimelineMediaPreviewItem: Equatable {
/// Wraps a media file and title to be previewed with QuickLook.
@Observable class Media: NSObject, QLPreviewItem, Identifiable {
fileprivate(set) var timelineItem: EventBasedMessageTimelineItemProtocol
var fileHandle: MediaFileHandleProxy?
fileprivate(set) var timelineItem: EventBasedMessageTimelineItemProtocol {
didSet { updatePreviewItemValues() }
}
var fileHandle: MediaFileHandleProxy? {
didSet { updatePreviewItemValues() }
}
var downloadError: Error?
init(timelineItem: EventBasedMessageTimelineItemProtocol) {
@@ -184,15 +191,22 @@ enum TimelineMediaPreviewItem: Equatable {
// MARK: QLPreviewItem
var previewItemURL: URL? {
fileHandle?.url
private let _previewItemURL = Mutex<URL?>(nil)
nonisolated var previewItemURL: URL? { // nonisolated as QuickLook can call from any thread (macOS 26).
_previewItemURL.withLock { $0 }
}
var previewItemTitle: String? {
switch fileHandle?.url {
case .some: filename
case .none: " " // Don't show any background text when the preview is still loading.
}
private let _previewItemTitle = Mutex<String?>(" ")
nonisolated var previewItemTitle: String? { // nonisolated as QuickLook can call from any thread (macOS 26).
_previewItemTitle.withLock { $0 }
}
private func updatePreviewItemValues() {
let url = fileHandle?.url
_previewItemURL.withLock { $0 = url }
// Don't show any background text (" ") while the preview is still loading.
_previewItemTitle.withLock { $0 = url == nil ? " " : filename }
}
// MARK: Event details
@@ -63,8 +63,8 @@ private struct PreviewView: UIViewControllerRepresentable {
}
private class PreviewItem: NSObject, QLPreviewItem {
var previewItemURL: URL?
var previewItemTitle: String?
nonisolated let previewItemURL: URL? // nonisolated as QuickLook can call from any thread (macOS 26).
nonisolated let previewItemTitle: String? // nonisolated as QuickLook can call from any thread (macOS 26).
init(previewItemURL: URL?, previewItemTitle: String?) {
self.previewItemURL = previewItemURL
@@ -289,8 +289,8 @@ private struct PreviewView: UIViewControllerRepresentable {
}
private class PreviewItem: NSObject, QLPreviewItem {
var previewItemURL: URL?
var previewItemTitle: String?
nonisolated let previewItemURL: URL? // nonisolated as QuickLook can call from any thread (macOS 26).
nonisolated let previewItemTitle: String? // nonisolated as QuickLook can call from any thread (macOS 26).
init(previewItemURL: URL?, previewItemTitle: String?) {
self.previewItemURL = previewItemURL