Swift 4: кнопка запускает то же действие в другом UITableViewCell - PullRequest
0 голосов
/ 20 октября 2018

У меня есть ячейка с 2 кнопками (для прослушивания и распознавания речи), надписью и текстовым полем.Я пытаюсь добиться того, чтобы при нажатии кнопки распознавания речи пользователь произносил содержимое, отображаемое в метке.Моя проблема с этим заключается в том, что кнопка прослушивания работает нормально в соответствии с indexPath.row, а говорящая кнопка - нет.Как и когда он активен, кнопка в другой ячейке тоже становится активной.И он записывает то же самое в этих ячейках.
Вы можете увидеть картину того, о чем я говорю здесь

Методы прослушивания (то есть синтезатора звука) и распознавания речив UITableViewCell.Я перепробовал все решения, которые смог найти в Интернете, но ни одно из них не сработало.Пробовал

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

, но проблема остается той же.Кроме того, я создал другой проект, и вместо того, чтобы использовать кнопку для распознавания речи, я просто использовал прямой ввод textField, но все равно возникает такая же проблема.

Кнопка в классе TableViewCell:

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

}

My 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

let audioEngine = AVAudioEngine () let speechRecognizer: SFSpeechRecognizer?= SFSpeechRecognizer (locale: Locale.init (идентификатор: "en-US"))

}

Я получаю данные из локального файла JSON, и это модель:

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

}

Возможно, кто-то может мне помочь с этим?

1 Ответ

0 голосов
/ 21 октября 2018

Здесь недостаточно кода для воссоздания вашей проблемы, в будущем предоставьте Минимальный, Полный и Проверяемый пример .К сожалению, никто не может предложить вам эффективное решение, которое поможет вам решить проблему, если они не смогут воссоздать проблему.

Однако я считаю, что понимаю, что вы пытаетесь выполнить:

  1. Объект модели, т.е. struct.
  2. Протокол с реализацией по умолчанию, одинаковой для всех ячеек.
  3. Класс TableViewCell, соответствующий протоколу, который вызывает протоколметоды.
  4. TableViewDelegate и источник данных для управления объектами из 1.

Рассмотрим следующее:

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» накаждая ячейка, идущая вниз, дает этот результат:

View Hierarchy with output

...