0

我有一个带有 2 个按钮(用于听力和语音识别)、标签和文本字段的单元格。What I am trying to achieve is when the speech recognition button is selected the user speaks the content that is displayed in a label. 我的问题是听按钮根据 indexPath.row 可以正常工作,但说话按钮不能。当它处于活动状态时,另一个单元格中的按钮也将变为活动状态。它在这些单元格中记录了相同的内容。
你可以看到我在这里谈论的图片

收听(即音频合成器)和语音识别的方法在 UITableViewCell 中。我已经尝试了所有可以在网上找到的解决方案,但都没有成功。试过

protocol RepeatCellDelegate: class {
    func buttonTapped(cell: RepeatCell)
}

但问题仍然存在。此外,已经创建了另一个项目,而不是使用按钮进行语音识别,我只是使用了直接 textField 输入,仍然会出现同样的问题。

TableViewCell 类中的按钮:

@IBAction func speakButtonPressed(_ sender: Any) {
self.delegate?.buttonTapped(cell: self)

}

我的cellForRowAt indexPath

let cell = tableView.dequeueReusableCell(withIdentifier: "RepeatCell") as! RepeatCell

cell.delegate = self

cell.conditionlabel.text = repeatTask[indexPath.row].conditionLabel

return cell

buttonTapped 函数检测单元格索引并记录语音输入。点击按钮后它会打印正确的单元格索引,但该操作也会在另一个单元格中触发。

func buttonTapped(cell: RepeatCell) {
guard let indexPath = self.repeatTV.indexPath(for: cell) else {
    return
}

cell.speakButton.isSelected = !cell.speakButton.isSelected

if (cell.speakButton.isSelected){
    self.recordAndRecognizeSpeech()
} else {
    audioEngine.inputNode.removeTap(onBus: 0)
    recognitionTask?.cancel()
}

print("Button tapped on row \(indexPath.row)")

}

// 语音输入识别器函数:

// variables for speech recognizer

让 audioEngine = AVAudioEngine() 让 SpeechRecognizer: SFSpeechRecognizer? = SFSpeechRecognizer(locale: Locale.init(identifier: "en-US")) 让请求 = SFSpeechAudioBufferRecognitionRequest() var recognitionTask: SFSpeechRecognitionTask?

// 语音函数 func recordAndRecognizeSpeech(){

let node = audioEngine.inputNode
let recordingFormat = node.outputFormat(forBus: 0)
node.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, _ in
    self.request.append(buffer)
}
audioEngine.prepare()

do {
    try audioEngine.start()
} catch {
    return print(error)
}

guard let myRecognizer = SFSpeechRecognizer() else {
    return
}
if !myRecognizer.isAvailable {
    return
}

recognitionTask = speechRecognizer?.recognitionTask(with: request, resultHandler: { (result, error) in
    if result != nil { //
        if let result = result{
            let cell = self.repeatTV.dequeueReusableCell(withIdentifier: "RepeatCell") as! RepeatCell
            let bestString = result.bestTranscription.formattedString
            if cell.speakButton.isSelected == true {
                cell.userInput.text = bestString
            }

        }else if let error = error{
            print(error)
        }
    }
})

}

我从本地 JSON 文件中获取数据,这是一个模型:

struct RepeatTask: Codable {
let name: String
let label: String
let conditionWord: String

}

也许有人可以帮我解决这个问题?

4

1 回答 1

0

这里没有足够的代码来重新创建您的问题,将来请提供一个最小、完整和可验证的示例。不幸的是,如果他们无法重现问题,没有人可以为您提供有效的解决方案来帮助您解决问题。

但是,我相信我了解您要完成的工作:

  1. 一个模型对象,即一个struct.
  2. 具有对所有单元相同的默认实现的协议。
  3. TableViewCell符合调用协议方法的协议的类。
  4. 用于管理 1 中的对象的 TableViewDelegate 和 Datasource。

考虑以下:

import UIKit

/// 1.
/// Data model for "Repeat Cell Objects"
struct RepeaterModel {
    var outputText:String?
    var inputAudio:Data?
}

/// 2.
/// Allows a cell to delegate listening and repeating (speaking)
protocol RepeatableCell {
    func listen()
    func speak()
}

// Extend your protocol to add a default implementation,
// that way you can just confrom to the protocol
// without implementing it every time, in every cell class.
extension RepeatableCell {
    func listen() {
        print("default implementation for listen")
    }

    func speak(){
        print("default implementation for speak")
    }

}



/// 3.
final class RepeatCell: UITableViewCell, RepeatableCell {

    // MARK: - Properties
    var model:RepeaterModel? {
        didSet {
            DispatchQueue.main.async {
                self.titleLabel.text = self.model?.outputText
            }
        }
    }

    // MARK: - Views
    lazy var listenButton: UIButton = {
        let btn = UIButton(type: .system)
        btn.setTitle("Listen", for: .normal)
        btn.addTarget(self, action: #selector(activateListen), for: .touchUpInside)
        btn.setTitleColor(.white, for: .normal)
        btn.backgroundColor = .blue
        btn.translatesAutoresizingMaskIntoConstraints = false
        return btn
    }()

    lazy var speakButton: UIButton = {
        let btn = UIButton(type: .system)
        btn.setTitle("Speak", for: .normal)
        btn.addTarget(self, action: #selector(activateSpeak), for: .touchUpInside)
        btn.setTitleColor(.white, for: .normal)
        btn.backgroundColor = .green
        btn.translatesAutoresizingMaskIntoConstraints = false
        return btn
    }()

    let titleLabel: UILabel = {
        let l = UILabel()
        l.translatesAutoresizingMaskIntoConstraints = false
        l.textColor = .black
        l.textAlignment = .center
        l.text = "No Text"
        return l
    }()

    //MARK: - Initializers
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        self.setup()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    //MARK: - Class Methods
    func setup() {
        self.contentView.addSubview(listenButton)
        self.contentView.addSubview(speakButton)
        self.contentView.addSubview(titleLabel)

        let spacing: CGFloat = 25.0

        //Listen top left
        listenButton.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: spacing).isActive = true
        listenButton.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: spacing).isActive = true
        listenButton.widthAnchor.constraint(equalToConstant: 100).isActive = true
        listenButton.heightAnchor.constraint(equalToConstant: 50).isActive = true

        // title label, center top.
        titleLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: spacing).isActive = true
        titleLabel.leadingAnchor.constraint(equalTo: self.listenButton.trailingAnchor, constant: spacing).isActive = true
        titleLabel.trailingAnchor.constraint(equalTo: self.speakButton.leadingAnchor, constant: -spacing).isActive = true
        titleLabel.heightAnchor.constraint(equalToConstant: 50).isActive = true

        //Speak top right
        speakButton.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: spacing).isActive = true
        speakButton.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor, constant: -spacing).isActive = true
        speakButton.widthAnchor.constraint(equalToConstant: 100).isActive = true
        speakButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
    }

    @objc func activateListen() {
        print("listen was pressed! on cell \(self.model?.outputText ?? "No Text")")
        /// The user wants to listen
        // call the delegate method..
        listen()
        // use self.model?.outputText
    }

    @objc func activateSpeak() {
        print("Speak was pressed! on cell \(self.model?.outputText ?? "No Text")")
        /// The user is speaking, record audio
        // call the delegate method..
        speak()
        //self.model?.inputAudio = somedata
    }
}



/// 4.
class ViewController: UITableViewController {

    // Array of your model objects
    var objects:[RepeaterModel] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.register(RepeatCell.self, forCellReuseIdentifier: "Repeat")
        // create or fetch model objects
        let items = [
            RepeaterModel(outputText: "1st Cell", inputAudio: nil),
            RepeaterModel(outputText: "2nd Cell", inputAudio: nil),
            RepeaterModel(outputText: "3rd Cell", inputAudio: nil),
            RepeaterModel(outputText: "4th Cell", inputAudio: nil),
            RepeaterModel(outputText: "5th Cell", inputAudio: nil),
            RepeaterModel(outputText: "6th Cell", inputAudio: nil),
            RepeaterModel(outputText: "8th Cell", inputAudio: nil),
            RepeaterModel(outputText: "9th Cell", inputAudio: nil),
            RepeaterModel(outputText: "10th Cell", inputAudio: nil),
            RepeaterModel(outputText: "11th Cell", inputAudio: nil),
            RepeaterModel(outputText: "12th Cell", inputAudio: nil)
        ]
        self.objects += items
    }


    //MARK: - TableView Methods

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        // 25 top spacing + 50 view element width + 25 bottom spacing
        return 100.0
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return objects.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if let cell = self.tableView.dequeueReusableCell(withIdentifier: "Repeat") as? RepeatCell {
            cell.model = objects[indexPath.row]
            // other cell stuff
            return cell
        }
        return UITableViewCell()
    }
}

在每个向下的单元格上按“Listen”然后“Speak”会产生以下输出:

查看带有输出的层次结构

于 2018-10-21T03:15:17.310 回答