es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Devuelve múltiples variables al completar el Controlador de Vista.

¿Cómo puedo pasar múltiples variables de vuelta en la finalización del controlador de vista sin usar estructuras o clases?
Aquí está mi código que funciona:

class TimerViewController: UIViewController {

    // CÓDIGO IRRELEVANTE ELIMINADO

    @IBAction func editTimerButtonPressed(_ sender: UIButton) {
        self.performSegue(withIdentifier: "goToEditTimer", sender: self)
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "goToEditTimer" {
            let destinationVC = segue.destination as! EditTimerViewController
            destinationVC.duration = Int(myTimer.totalTime)
            destinationVC.timerName = myTimer.timerName
            destinationVC.completion = { [weak self] duration, name in
                DispatchQueue.main.async {
                    self?.myTimer.totalTime = Double(duration!)
                    self?.timerLabel.text = name!
                    self?.timer.invalidate()
                }
            }
        }
    }
}

class EditTimerViewController: UIViewController, UITextFieldDelegate {

    var duration: Int? // la duración del temporizador se pasa desde Timer
    var timerName: String?
    public var completion: ((Int?, String?) -> Void)?

    // CÓDIGO IRRELEVANTE ELIMINADO

    @IBAction func savePressed(_ sender: UIButton) {
        timerName = timerNameField.text
        completion?(duration, timerName)
        self.dismiss(animated: true, completion: nil)
    }
}

Pero ahora quiero pasar los cambios realizados no solo a la duration, sino también al timerName.

ACTUALIZACIÓN

Siguiendo el consejo de @koen, intenté poner ambas variables en una tupla, pero obtuve un error que no puedo entender.

Aquí declaro timerData como una tupla de (Int?, String?) pero obtengo un error que el tipo de argumento esperado es Int?:

class EditTimerViewController: UIViewController, UITextFieldDelegate {

    var duration: Int? // la duración del temporizador se pasa desde Timer
    var timerName: String?
    public var completion: ((Int?, String?) -> Void)?

    // CÓDIGO IRRELEVANTE ELIMINADO

    @IBAction func savePressed(_ sender: UIButton) {
        timerName = timerNameField.text
        let timerData = (duration: duration, name: timerName)
        completion?(timerData) // ERROR Cannot convert value of type '(duration: Int?, name: String?)' to expected argument type 'Int?'
        self.dismiss(animated: true, completion: nil)
    }
}

Pero estoy recibiendo errores para las siguientes cadenas:

self?.myTimer.totalTime = Double(timerData[0]!)
self?.timerLabel.text = String(timerData[1]!)

Pero no lo estoy declarando en el VC principal:

class TimerViewController: UIViewController {

    // CÓDIGO IRRELEVANTE ELIMINADO
    // timerData no fue declarado

    @IBAction func editTimerButtonPressed(_ sender: UIButton) {
        self.performSegue(withIdentifier: "goToEditTimer", sender: self)
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "goToEditTimer" {
            let destinationVC = segue.destination as! EditTimerViewController
            destinationVC.duration = Int(myTimer.totalTime)
            destinationVC.timerName = myTimer.timerName
            let timerData = (duration: destinationVC.duration, name: destinationVC.timerName)
            destinationVC.completion = { [weak self] timerData in // si verifico timerData, se describe como Declaración let timerData: Int? Declarado en TimerViewController.swift
                DispatchQueue.main.async {
                    self?.myTimer.totalTime = Double(timerData.duration!) // ERROR  Argument passed to call that takes no arguments + ERROR Value of type 'Int?' has no member 'duration'
                    self?.timerLabel.text = timerData.name // ERROR  Argument passed to call that takes no arguments + ERROR Value of type 'Int?' has no member 'duration'
                    self?.timer.invalidate()
                }
            }
        }
    }
}
Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para devolver varias variables en la finalización del Controlador de Vista sin usar structs o clases, se pueden utilizar tuplas. Las tuplas permiten agrupar varios valores de cualquier tipo en un solo valor compuesto.

    Para devolver tanto la duración como el nombre del temporizador desde EditTimerViewController a TimerViewController, se puede definir una tupla con estos valores:

    var timerData = (duración: duración, nombre: nombreDelTemporizador)
    

    Luego, pase esta tupla al cierre de completion en EditTimerViewController:

    completion?(timerData)
    

    En TimerViewController, puede recibir esta tupla y acceder a sus valores:

    destinationVC.completion = { [weak self] timerData in
      DispatchQueue.main.async {
        self?.myTimer.totalTime = Double(timerData.duración)
        self?.timerLabel.text = String(timerData.nombre)
        self?.timer.invalidate()
      }
    }
    

    Asegúrese de actualizar el tipo de completion en EditTimerViewController para aceptar una tupla:

    public var completion: ((Int?, String?) -> Void)?
    

    Tenga en cuenta que si recibe errores al intentar acceder a los valores de la tupla, asegúrese de acceder correctamente a las propiedades de la tupla por su nombre, según se define al crear la tupla.

Comments are closed.