最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

swift - How to trigger the new Format Panel (iOS 18) via a button press in UITextView? - Stack Overflow

programmeradmin1浏览0评论

I'm trying to programmatically trigger the appearance of the new Format Panel introduced in the WWDC24 session "What's new in UIKit" when a button is pressed.

So far, I've enabled text formatting by setting allowsEditingTextAttributes = true. This works for showing the Format Panel through the edit menu (when long-pressing or selecting text). However, I can't find a way to make the panel appear directly via a button press in the keyboard toolbar.

Does anyone know if this is possible? If so, how?

Here’s the (simplified) code I’m working with:

struct TextEditorView: UIViewRepresentable {
    @Binding var text: NSAttributedString

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    func makeUIView(context: Context) -> UITextView {
        let textEditorView = UITextView()
    
        textEditorView.addToolbar()
        textEditorView.allowsEditingTextAttributes = true
        textEditorView.delegate = context.coordinator
        
        return textEditorView
    }
    
    func updateUIView(_ uiView: UITextView, context: Context) {
        uiView.attributedText = text
    }
    
    class Coordinator: NSObject, UITextViewDelegate {
    
        var parent: TextEditorView
    
        init(_ uiTextView: TextEditorView) {
            self.parent = uiTextView
        }
    
        func textViewDidChange(_ textView: UITextView) {
            self.parent.text = textView.attributedText
        }
    }
}
extension UITextView {
    func addToolbar() {
        let toolbar = UIToolbar()

        let formatButton = UIBarButtonItem(
            image: UIImage(systemName: "textformat.alt"),
            style: .plain,
            target: self,
            action: #selector(showTextFormattingPanel)
        )
        
        toolbar.items = [formatButton]
        self.inputAccessoryView = toolbar
    }
    
    @objc private func showTextFormattingPanel() {
        // ? Show Format Panel ?
    }
}

I'm trying to programmatically trigger the appearance of the new Format Panel introduced in the WWDC24 session "What's new in UIKit" when a button is pressed.

So far, I've enabled text formatting by setting allowsEditingTextAttributes = true. This works for showing the Format Panel through the edit menu (when long-pressing or selecting text). However, I can't find a way to make the panel appear directly via a button press in the keyboard toolbar.

Does anyone know if this is possible? If so, how?

Here’s the (simplified) code I’m working with:

struct TextEditorView: UIViewRepresentable {
    @Binding var text: NSAttributedString

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    func makeUIView(context: Context) -> UITextView {
        let textEditorView = UITextView()
    
        textEditorView.addToolbar()
        textEditorView.allowsEditingTextAttributes = true
        textEditorView.delegate = context.coordinator
        
        return textEditorView
    }
    
    func updateUIView(_ uiView: UITextView, context: Context) {
        uiView.attributedText = text
    }
    
    class Coordinator: NSObject, UITextViewDelegate {
    
        var parent: TextEditorView
    
        init(_ uiTextView: TextEditorView) {
            self.parent = uiTextView
        }
    
        func textViewDidChange(_ textView: UITextView) {
            self.parent.text = textView.attributedText
        }
    }
}
extension UITextView {
    func addToolbar() {
        let toolbar = UIToolbar()

        let formatButton = UIBarButtonItem(
            image: UIImage(systemName: "textformat.alt"),
            style: .plain,
            target: self,
            action: #selector(showTextFormattingPanel)
        )
        
        toolbar.items = [formatButton]
        self.inputAccessoryView = toolbar
    }
    
    @objc private func showTextFormattingPanel() {
        // ? Show Format Panel ?
    }
}
Share Improve this question asked Nov 20, 2024 at 16:10 KonradKonrad 235 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

There is no public API for triggering the display of the new formatting screen of a UITextView. When you select the new Format -> More... context menu in a UITextView, it results in a call to the private API _showTextFormattingOptions:. So one solution is to directly call that private API:

@objc private func showTextFormattingPanel() {
    // Show Format Panel
    self.perform(NSSelectorFromString("_showTextFormattingOptions:"), with: self)
}

This does work in a test development app. But this is far from ideal. It's quite possible this could cause an app rejection for using a private API. That's easy to avoid though will a little obfuscation of the selector string. The bigger problem is that the private API could change in a future iOS update which would result in the app crashing due to calling an unrecognized selector.

A much more difficult solution would be to create and present your own instance of UITextFormattingViewController. You would need to provide a delegate to handle all of the value changes and you would then need to manually apply them to the text view. This solution would be a lot more work. It also replicates all of the built-in functionality provided by the private API of UITextView. And the UITextFormattingViewController documentation contains no comments so it's really hard to know how many of the APIs work.

发布评论

评论列表(0)

  1. 暂无评论