0

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?

kelalaka
  • 5,064
  • 5
  • 27
  • 44
  • 1
    I remember hitting this and in my situation, I broke identity by having an `if` branch. In my situation, it didn't matter because the `Text` wasn't affected by animation. – jnpdx Mar 27 '23 at 14:20
  • @jnpdx good points. Fortunately, I don't have animation for these Text, too. Thanks. – kelalaka Mar 27 '23 at 14:34

1 Answers1

2

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)
ScottM
  • 7,108
  • 1
  • 25
  • 42
  • Great. Thanks. Sometimes, I wonder what is in the minds of the developers. – kelalaka Mar 27 '23 at 14:06
  • To be honest, I think the ability to make text selectable dynamically might not be the best UX experience. Generally if it makes sense for text to be selectable, then it can selectable all the time. So for 95% of occasions, those are decisions that can be made at design time. If your use case falls in the other 5%, code like the above can give you the ability. – ScottM Mar 27 '23 at 14:12