Как редактировать и передавать данные ячейки с делегатом и протоколом в Swift - PullRequest
0 голосов
/ 30 декабря 2018

У меня есть два VC, первый - tableView, второй - подробный VC, где вы можете добавить новый элемент в tableView.Я реализовал передачу данных вперед с segues (от кнопки «плюс» в первом VC) и обратно с делегатом и протоколом при добавлении нового элемента в tableView (срабатывает при нажатии кнопки сохранения на втором VC).

Я добавил переход из ячейки прототипа во второй ВК (подробный вид), мне также удалось протестировать в первом ВК, который запускается, т. Е. Добавить новый элемент или перейти к подробному представлению этого элемента.проблема, с которой я сталкиваюсь, кнопка сохранения во втором VC больше не работает (и кнопка отмены также), я хочу иметь возможность редактировать текстовые поля во втором VC и нажать кнопку сохранения, чтобы сохранить отредактированный элемент обратнов первом.Я нашел способ реализовать это с помощью раскручивающихся сегментов, однако я хотел бы знать, как это сделать с делегатом?

Мой первый код VC:

class ThingsTableViewController: UITableViewController, CanReceive {

    var myThings = [Thing]()

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

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

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)

        cell.textLabel?.text = myThings[indexPath.row].name
        cell.detailTextLabel?.text = myThings[indexPath.row].type

        return cell
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        if segue.identifier == "addNewThing" {

            let secondVC = segue.destination as! UINavigationController

            let ThingsViewController = secondVC.topViewController as! ThingsViewController

            ThingsViewController.delegate = self

        } else if segue.identifier == "showDetail" {

            guard let thingDetailViewController = segue.destination as? ThingsViewController else {fatalError("Unknown Destination")}

            guard let selectedCell = sender as? UITableViewCell else {
                fatalError("Unexpected sender: \(sender)")
            }

            guard let indexPath = tableView.indexPath(for: selectedCell) else {
                fatalError("The selected cell is not being displayed by the table")
            }

            let selectedThing = myThings[indexPath.row]
            thingDetailViewController.thing = selectedThing

        }
    }

    func dataReceived(data: Thing) {

        if let selectedIndexPath = tableView.indexPathForSelectedRow {

        myThings[selectedIndexPath.row] = data
        tableView.reloadRows(at: [selectedIndexPath], with: .none)

        } else {

        myThings.append(data)
        tableView.reloadData()



    }

}

код во втором виртуальном каналевыглядеть так:

 protocol CanReceive {

func dataReceived(data: Thing)

    }

}

class ThingsViewController: UIViewController, UITextFieldDelegate {

    var delegate : CanReceive?
    var thing : Thing?

    @IBOutlet weak var thingNameTextField: UITextField!

    @IBOutlet weak var thingTypeTextfield: UITextField!

    @IBAction func saveThingButton(_ sender: UIBarButtonItem) {
        let newThing = Thing(name: thingNameTextField.text!, type: thingTypeTextfield.text!)

        delegate?.dataReceived(data: newThing)

        self.dismiss(animated: true, completion: nil)
        self.navigationController?.popViewController(animated: true)

    }

    @IBAction func cancelButton(_ sender: UIBarButtonItem) {
        self.dismiss(animated: true, completion: nil)
        self.navigationController?.popViewController(animated: true) 
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        thingNameTextField.delegate = self

        updateSaveButtonState()

        if let thing = thing {
            navigationItem.title = thing.name
            thingNameTextField.text = thing.name
            thingTypeTextfield.text = thing.type

        }
    }

    // MARK: UITextField Delegate

    // get triggered when the user hit the return key on the keyboard
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        thingNameTextField.resignFirstResponder()
        self.navigationItem.rightBarButtonItem?.isEnabled = true
        return true
    }

    //gives chance to read info in text field and do something with it
    func textFieldDidEndEditing(_ textField: UITextField) {
        updateSaveButtonState()
        navigationItem.title = thingNameTextField.text
    }

    func updateSaveButtonState() {

        let text = thingNameTextField.text
        self.navigationItem.rightBarButtonItem?.isEnabled = !text!.isEmpty
    }

}

Ответы [ 3 ]

0 голосов
/ 30 декабря 2018

Объявите протокол для получения данных.

protocol ViewControllerDelegate: class {
func didTapButton(with data: Int)
}

объявите делегат протокола, в который вы отправляете данные

class SecondVC: UIViewController {

weak var delegate: ViewControllerDelegate?

@IBAction func buttonPressed(_ sender: UIButton) {
    delegate?.didTapButton(with: sender.tag)
}

}

подтвердите протокол, в который вы хотите получить данныеи сделай делегата себе.

class FirstVC : UIViewController,ViewControllerDelegate {


override func viewDidLoad() {
    super.viewDidLoad()

}

func gotoSecond() {
    let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "identifier") as! SecondVC
    vc.delegate = self
    self.navigationController?.pushViewController(vc, animated: true)
}

func didTapButton(with data: Int) {
    print(data)
}


}
0 голосов
/ 30 декабря 2018

Вы устанавливаете delegate для случая, когда идентификатор segue равен addNewThing, но как насчет случая, когда этот идентификатор равен showDetail?

Установите delegate пункта назначения segue для случая, когда идентификатор segue равен showDetail

if segue.identifier == "addNewThing" {
    ...
} else if segue.identifier == "showDetail" {
    ...
    thingDetailViewController.delegate = self
    ...
}

Затем, когда вам нужно отключить встраивание ViewController в контроллер навигации, просто отклоните его изатем отклонить навигационный контроллер

0 голосов
/ 30 декабря 2018

В ThingsViewController классе, определите делегата с weak var

weak var delegate: CanReceive?

Еще одна проблема наблюдается,

Похоже, что имя вашего экземпляра и имя класса совпадают, пожалуйста, обновитеимя экземпляра,

if segue.identifier == "addNewThing" {
    let secondVC = segue.destination as! UINavigationController
    let thingsVC = secondVC.topViewController as! ThingsViewController
    thingsVC.delegate = self 
} else if segue.identifier == "showDetail" { 
    guard let thingDetailViewController = segue.destination as? 
    ThingsViewController else {fatalError("Unknown Destination")}

        guard let selectedCell = sender as? UITableViewCell else {
            fatalError("Unexpected sender: \(sender)")
        }

        guard let indexPath = tableView.indexPath(for: selectedCell) else {
            fatalError("The selected cell is not being displayed by the table")
        }

        let selectedThing = myThings[indexPath.row]
        thingDetailViewController.thing = selectedThing
        thingDetailViewController.delegate = self
}

Ваш tableView.reloadData() должен произойти в main queue

func dataReceived(data: Thing) {
    myThings.append(data)
    DispatchQueue.main.async {
        tableView.reloadData()
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...