首页 > 解决方案 > 在 SwiftUI 中突出显示语音

问题描述

我没有成功在 SwiftUI 中突出显示文本。我只在 UIKit 中找到了它的例子。在 UIKit 中它应该是var label: UILabel!,但在 SwiftUI 中标签必须是 String。我试图转换NSMutableAttributedStringString格式,内部函数,但它在抱怨。如何使用String格式来解决它,以便它也可以在 SwiftUI 中使用?

import AVFoundation

class Speaker: NSObject {
    let synth = AVSpeechSynthesizer()
    var label: String // <- problem
    

    override init() {
        super.init()
        synth.delegate = self
    }

    func speak(_ string: String) {
        let utterance = AVSpeechUtterance(string: string)
        utterance.voice = AVSpeechSynthesisVoice(language: "en-GB")
        utterance.rate = 0.4
        synth.speak(utterance)
    }
    
    // Functions to highlight text
    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, willSpeakRangeOfSpeechString characterRange: NSRange, utterance: AVSpeechUtterance) {
        let mutableAttributedString = NSMutableAttributedString(string: utterance.speechString)
        mutableAttributedString.addAttribute(.foregroundColor, value: UIColor.red, range: characterRange)
        label.attributedText = mutableAttributedString
    }

    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
        label.attributedText = NSAttributedString(string: utterance.speechString)
    }
}

标签: swiftswiftuiavfoundation

解决方案


我建议您换行UILabelUIViewRepresentable以便您可以像以前一样继续使用属性字符串:


struct ContentView : View {
    @ObservedObject var speaker = Speaker()
    
    var body: some View {
        VStack {
            LabelRepresented(text: speaker.label)
        }.onAppear {
            speaker.speak("Hi. This is a test.")
        }
    }
}

struct LabelRepresented: UIViewRepresentable {
    var text : NSAttributedString?
    
    func makeUIView(context: Context) -> UILabel {
        return UILabel()
    }
    
    func updateUIView(_ uiView: UILabel, context: Context) {
        uiView.attributedText = text
    }
}

class Speaker: NSObject, ObservableObject, AVSpeechSynthesizerDelegate {
    let synth = AVSpeechSynthesizer()
    @Published var label: NSAttributedString? // <- change to AttributedString
    

    override init() {
        super.init()
        synth.delegate = self
    }

    func speak(_ string: String) {
        let utterance = AVSpeechUtterance(string: string)
        utterance.voice = AVSpeechSynthesisVoice(language: "en-GB")
        utterance.rate = 0.4
        synth.speak(utterance)
    }
    
    // Functions to highlight text
    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, willSpeakRangeOfSpeechString characterRange: NSRange, utterance: AVSpeechUtterance) {
        let mutableAttributedString = NSMutableAttributedString(string: utterance.speechString)
        mutableAttributedString.addAttribute(.foregroundColor, value: UIColor.red, range: characterRange)
        label = mutableAttributedString
    }

    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
        label = NSAttributedString(string: utterance.speechString)
    }
}

我更改label为 anNSAttributedString?并将其设置为 an 上的 @Published 属性ObservableObject——这样,当它更改时,视图会立即得到通知。

UIViewRepresentable创建一个标签,并在其更改时使用属性字符串对其进行更新。

如果您确实想尝试更纯粹的 SwiftUI 方法,这篇博文有一些在 SwiftUI 中使用 NSAttributedString 的好资源(包括我采用的方法):https ://swiftui-lab.com/attributed-strings-with -swiftui/


推荐阅读