SwiftUI ViewBuilder and non-sendable type 'Binding<Bool>' in a `@Sendable` closure

489 views Asked by At

I have a ViewBuilder that I use to lock/unlock some views. It uses a Binding to pass the locked/unlocked State.

I am now getting this warning on the if line:

Capture of 'isUnlocked' with non-sendable type 'Binding' in a @Sendable closure

extension View {
    @ViewBuilder
    func requestUnlock(isUnlocked: Binding<Bool>) -> some View {
        
        self.task {
            if isUnlocked.wrappedValue == false {
                let unlocked = await Unlock.authenticate()
                isUnlocked.wrappedValue = unlocked
            }
        }
    }
}

As this is an extension of View I cannot add or ignore Sendable compliance and i'm not sure what magic is needed for me to clear this warning.

1

There are 1 answers

0
jrturton On BEST ANSWER

Create a view modifier instead and let SwiftUI handle the updates and actor isolation for you via the property wrapper:

struct UnlockRequester: ViewModifier {
    @Binding var isUnlocked: Bool
    
    func body(content: Content) -> some View {
        content.task {
            if isUnlocked == false {
                isUnlocked = await Unlock.authenticate()
            }
        }
    }
}

Then:

extension View {
    func requestUnlock(isUnlocked: Binding<Bool>) -> some View {
        self.modifier(UnlockRequester(isUnlocked: isUnlocked))
    }
}

This gives no warnings even with strict concurrency checking enabled.