How to fix MainActor warning for QLPreviewControllerDelegate

I'm currently migrating a midsize (20k LOC) project to Swift structured concurrency. With complete checking turned on, it currently builds with only two warnings, both of which are related to the QLPreviewControllerDelegate protocol:

"Main actor-isolated instance method 'previewControllerDidDismiss' cannot be used to satisfy nonisolated protocol requirement; this is an error in the Swift 6 language mode" as well as the same warning but substituting 'previewController(_:transitionViewFor:)' for the method name.

I'm confused as to how to make these nonisolated, as they use UIKit classes/subclasses as arguments and/or return types.

Answered by DTS Engineer in 812610022

I only have limited experience with QLPreviewController but I’m presuming that the QLPreviewControllerDelegate methods will only ever be called on the main thread. Does that gel with your expectations?

If so, the correct fix for this is for QuickLook framework to add annotations that tell the compiler about this constraint. I encourage you to file a bug requesting that. Please post your bug number, just for the record.

In the meantime, you can work around this like so:

final class MainViewController: UIViewController, @preconcurrency QLPreviewControllerDelegate {

    func previewControllerDidDismiss(_ controller: QLPreviewController) {
        … your code here …
    }
}

Note the @preconcurrency on the QLPreviewControllerDelegate conformance. This tells the compiler that you believe that the methods in QLPreviewControllerDelegate can only be called on the main actor. That silences these warnings but also adds an assert to your implementation. That way you’ll trap if your assumptions are wrong.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Accepted Answer

I only have limited experience with QLPreviewController but I’m presuming that the QLPreviewControllerDelegate methods will only ever be called on the main thread. Does that gel with your expectations?

If so, the correct fix for this is for QuickLook framework to add annotations that tell the compiler about this constraint. I encourage you to file a bug requesting that. Please post your bug number, just for the record.

In the meantime, you can work around this like so:

final class MainViewController: UIViewController, @preconcurrency QLPreviewControllerDelegate {

    func previewControllerDidDismiss(_ controller: QLPreviewController) {
        … your code here …
    }
}

Note the @preconcurrency on the QLPreviewControllerDelegate conformance. This tells the compiler that you believe that the methods in QLPreviewControllerDelegate can only be called on the main actor. That silences these warnings but also adds an assert to your implementation. That way you’ll trap if your assumptions are wrong.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

IMO this definitely should be marked @MainActor (reported as FB14256770) but thanks for the workaround!

How to fix MainActor warning for QLPreviewControllerDelegate
 
 
Q