swiftuiselectionswiftui-text

SwiftUI toggle Text selection with .enabled and .disabled


Enabling text selection statically works fine as in this answer

simply;

Text("Selectable text")
    .textSelection(.enabled)
Text("Non selectable text")
    .textSelection(.disabled)

I want text are selectible according to user's preferences, some annoys with selection. So; I've expected that the below runs perfectly;

Text("Sample Text)
    .textSelection( enableSelection ? .enabled : .disabled)

Xcode 14.2 provides two errors;

Member 'disabled' in 'EnabledTextSelectability' produces result of type 'DisabledTextSelectability', but context expects 'EnabledTextSelectability'

and

Static property 'disabled' requires the types 'EnabledTextSelectability' and 'DisabledTextSelectability' be equivalent

How can we solve this issue so that we can toggle the selection in real time?


Solution

  • Yes, unfortunately the way that the textSelection parameter accepts a value that conforms to TextSelectability means that this isn't really possible in a single step.

    While we can in theory create custom objects that conform to TextSelectability, any conforming object has to have a static allowsSelection property that's either true or false. That means it can't change dynamically.

    An alternative is to roll something ourselves, that applies one or other of the modifiers based on a Boolean:

    struct DynamicTextSelection: ViewModifier {
        var allowsSelection: Bool
    
        func body(content: Content) -> some View {
            if allowsSelection {
                content.textSelection(.enabled)
            } else {
                content.textSelection(.disabled)
            }
        }
    }
    
    extension View {
        func dynamicTextSelection(_ allowsSelection: Bool) -> some View {
            self.modifier(DynamicTextSelection(allowsSelection: allowsSelection))
        }
    }
    

    Then at the point of use this becomes:

    Text("My text, which may or not be selectable")
      .dynamicTextSelection(allowSelection)