[tvOS] ScrollView with Text does not scroll

I'm trying to do something so seemingly basic, yet I can't get it to work and I'm flummoxed.

In a basic, vanilla SwiftUI app for tvOS, embed a single Text element with a very long string (hundreds of lines) in it:

struct ContentView: View {
  var body: some View {
    ScrollView(.vertical) {
      Text(veryLargeString)
        .focusable()
    }
  }
}

Then fire up the app on tvOS, and it will not scroll. No matter what I do. Pressing arrow keys, swiping fast with my thumb, and nothing. It will not move. Ironically, in the Xcode SwiftUI Preview window—it does scroll, so that's always a fun tease.

What I do know is that the focus engine is throwing a few errors, so it's leading me to believe the issue is with how I have the focusable element attached. I'm using a combination of -UIFocusLoggingEnabled YES as well as listening for UIFocusSystem.movementDidFailNotification.

Unfortunately since this is SwiftUI, the notification failure and debugging logs aren't really all that actionable. Help appreciated!

Filed FB13691987

I have the same issue just now.


    public var body: some View {
        ScrollView {
            Text(attributedLicenseBody)
                .font(.caption)
                .frame(maxWidth: .infinity, alignment: .leading)
                .padding()
                .onAppear {
                    attributedLicenseBody = attribute(library.licenseBody)
                }
        }
        .navigationBarTitle(library.name)
        ._licenseViewStyle(licenseViewStyle) {
            if let url = library.url {
                openURL(url)
            }
        }
        .background(licenseViewStyle.background)
    }

That codes scroll nicely on iOS.

It appears to me that it is possible to use UITextView instead of Text. And with that, you end up with a scrollable element (interestingly completely without using scrollview.

Note, in the example below I also used attributified text to render html elements for styling. So even that works. But it also works with just a regular text string!

    Rectangle()
        .fill(.ultraThinMaterial)
        .ignoresSafeArea()

    FocusableAttributedTextView(attributedString: viewModel.attributedString)
        .frame(width: 500,
                height: 800)
        .background(.ultraThinMaterial)
        .clipShape(RoundedRectangle(cornerRadius: Constants.cornerRadius))
        .focused($isFocused)
}
.onExitCommand {
    showExpanded = false
}
struct FocusableAttributedTextView: UIViewRepresentable {
    let attributedString: AttributedString

    func makeUIView(context: Context) -> UITextView {
        let textView = UITextView()

        // Configure for tvOS focus and scrolling as per Cocoanetics/DTCoreText#1149
        textView.isSelectable = true
        textView.isUserInteractionEnabled = true
        textView.panGestureRecognizer.allowedTouchTypes = [NSNumber(value: UITouch.TouchType.indirect.rawValue)]
        textView.font = UIFont.systemFont(ofSize: 90)

        return textView
    }

    func updateUIView(_ uiView: UITextView, context: Context) {
        // Convert SwiftUI AttributedString to NSAttributedString for UITextView
        let nsAttributedString = NSAttributedString(attributedString)
        uiView.attributedText = nsAttributedString
    }
}
[tvOS] ScrollView with Text does not scroll
 
 
Q