Is it possible to implement custom SwiftUI layouts in Swift 6?

import SwiftUI

@MainActor
struct Example: @preconcurrency Layout {
    @MainActor
    class Cache {
        init() {}
    }

    func makeCache(subviews: Self.Subviews) -> Self.Cache {
        Cache()
    }

    func updateCache(_ cache: inout Self.Cache,
                     subviews: Self.Subviews) {}

    …
}

The Swift 6 compiler complains:

warning: non-sendable type 'Self.Cache' in parameter of the protocol requirement satisfied by main actor-isolated instance method 'updateCache(_:subviews:)' cannot cross actor boundary; this is an error in the Swift 6 language mode

The @preconcurrency is necessary because Layout lacks the correct @MainActor annotation. But it seems like the compiler doesn't fully understand the ramifications - it seems to believe an isolation boundary is being crossed when in fact it is not (every type & method here is bound to the main actor).

I'm a bit stumped as to how to get around this.

(the @preconcurrency attribute seemingly isn't a viable part of the solution anyway since the Swift 5.10 compiler barfs on it, but we're not at that bridge yet - I'll be happy to first get this code to work in Swift 6 at all)

I think the nonisolated workaround (with MainActor.assumeIsolated) should compile from 5.10. I'm using this now and it seems to be ok.

Layout will eventually (I assume) be updated by the SwiftUI team in one of the next betas so that these workarounds are no longer needed.

1 Like