【问题标题】:passing data from screen to screen xcode?将数据从屏幕传递到屏幕xcode?
【发布时间】:2017-04-19 01:35:23
【问题描述】:

我的 ViewController1 中有这段代码

var calendarios = [Calendario]()
var totalCalendarios1 = 0

(当屏幕加载 totalCalendarios 更改并正确显示总数时,我可以在调试中看到它) 我希望它传递给我的 ViewController2,我已经制作了这段代码:

let copiaCalendarios = ViewController1()
let totalCalendarios2 = copiaCalendarios.totalCalendarios1

我打印了第二个值,它总是说 0,之前没关系。

我也用过这段代码:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let destino = segue.destination as? ViewController
        destino?.calendariosCopia = calendarios
    }

但不起作用。 我究竟做错了什么? 已搜索信息,但已过时

编辑: 这是我的原始代码: CalendarioViewController 是我的第二个 VC,CalendarioTableViewController 是我的第一个 VC 并且是发送者。

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let destino = segue.destination as? CalendarioViewController
        destino?.calendariosCopia = calendarios
    }

这是我用过的代码,这个也是:

let copiaCalendarios = CalendarioTableViewController()
let totalCalendarios = copiaCalendarios.totalCalendarios

在两个VC中都有一个var totalCalendarios = 0

Thx ind提前并为我的英语不好感到抱歉:$

编辑2: segue的种类有关系吗? 因为我用的是'Present Modally'

编辑3: CalendarioTableViewController:

//
//  CalendarioTableViewController.swift
//  Vizion5
//
//  Created by ROB on 16/04/17.
//  Copyright © 2017 ROB. All rights reserved.
//

import UIKit

class CalendarioTableViewController: UITableViewController {

    var calendarios = [Calendario]()
    var totalCalendarios = 0

    func cargarEjemplos() {

        guard let calendario1 = Calendario(nombre: "2017-A", fin: "17/01/2017", inicio: "05/05/2017") else {
            fatalError("Error en calendario table view controller")
        }

        guard let calendario2 = Calendario(nombre: "2016-A", fin: "17/01/2016", inicio: "05/05/2016") else {
            fatalError("Error en calendario table view controller")
        }

        calendarios += [calendario1, calendario2]

    }

    func contarCalendarios() {
        totalCalendarios = calendarios.count
    }

    //AÑADIDO AUTOMATICAMENTE

    override func viewDidLoad() {
        super.viewDidLoad()

        //CARGA LOS EJEMPLOS
        cargarEjemplos()
        contarCalendarios()

        // Uncomment the following line to preserve selection between presentations
        // self.clearsSelectionOnViewWillAppear = false

        // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
        // self.navigationItem.rightBarButtonItem = self.editButtonItem()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // MARK: - Table view data source

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

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

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        //let identificadorCelda = "tablaCalendario"
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "tablaCalendario", for: indexPath) as? CalendarioTableViewCell
            else {
                fatalError("error 1: calendario table controller")
        }

        let calendario = calendarios[indexPath.row]

        // Configure the cell...

        cell.nombreCalendario.text = calendario.nombre
        cell.finCalendario.text = calendario.fin
        cell.inicioCalendario.text = calendario.inicio

        return cell
    }

    //MARK: ACCIONES
    @IBAction func regresarATablaCalendario(sender: UIStoryboardSegue) {
        if let viewControllerOrigen = sender.source as? CalendarioViewController, let calendario = viewControllerOrigen.calendario {
            //AÑADE EL NUEVO CALENDARIO
            let newIndexPath = IndexPath(row: calendarios.count, section: 0)
            calendarios.append(calendario)
            tableView.insertRows(at: [newIndexPath], with: .automatic)
        }
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        print("Total calendarios es: " + String(totalCalendarios))
        let destino = segue.destination as? CalendarioViewController // here you have to use the exact name of your Second View Controller instead of ViewController
        destino?.totalCalendarios = totalCalendarios
    }

}

我的 CalendarioViewController

//
//  CalendarioViewController.swift
//  Vizion5
//
//  Created by ROB on 16/04/17.
//  Copyright © 2017 ROB. All rights reserved.
//

import UIKit

class CalendarioViewController: UIViewController, UITextFieldDelegate, UINavigationControllerDelegate {

    @IBOutlet weak var nombreCalendario: UITextField!
    @IBOutlet weak var fechaInicioCalendario: UIDatePicker!
    @IBOutlet weak var fechaFinCalendario: UIDatePicker!
    @IBOutlet weak var botonGuardar: UIBarButtonItem!

    var totalCalendarios = 0

    //ESTE VALOR SERA PASADO POR 'CALENDARIOVIEWCONTROLLER' EN 'PREPARE(FOR: SENDER:)' O CONTRUIDO PARA AGREGAR UN NUEVO CALENDARIO
    var calendario: Calendario?

    override func viewDidLoad() {
        super.viewDidLoad()
        nombreCalendario.delegate = self //SE CONTROLA A SI MISMO

        print("Total segue: " + String(totalCalendarios))

        //CHECA SI SE PUEDE HABILITAR EL BOTON DE GAURDADO
        //DESABILITA EL BOTON DE GUARDADO
        botonGuardar.isEnabled = false
        //actualizaEstadoBotonGuardar()

        // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    //MARK: FUNCIONES DE TECLADO Y DETERMINAR FECHA (QUE EL FIN SEA MAYOR QUE INICIO)

    func textFieldDidBeginEditing(_ textField: UITextField) {
        botonGuardar.isEnabled = false
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        //SE DESHABILITA EL BOTON DE GUARDAR CUANDO SE ESCRIBE
        botonGuardar.isEnabled = false
        //ESCONDE EL TECLADO AL PRESIONADO "HECHO" (DONE)
        textField.resignFirstResponder()
        return true
    }

    func textFieldDidEndEditing(_ textField: UITextField) {
        actualizaEstadoBotonGuardar()
        //navigationItem.title = textField.text
    }


    // MARK: - NAVEGACION (UNWIND SEGUE)
    @IBAction func botonCancelar(_ sender: UIBarButtonItem) {
        dismiss(animated: true, completion: nil)
    }

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        //super.prepare(for: segue, sender: sender)
        guard let button = sender as? UIBarButtonItem, button === botonGuardar else {
            print("Error en prepare sender")
            return
        }

        let setFormatoFecha = DateFormatter()
        setFormatoFecha.dateFormat = "dd/MM/yyyy"

        let nombre = nombreCalendario.text
        let fin = setFormatoFecha.string(from: fechaFinCalendario.date)
        let inicio = setFormatoFecha.string(from: fechaInicioCalendario.date)

        //SE INSERTAN LOS DATOS LEIDOS.
        calendario = Calendario(nombre: nombre!, fin: fin, inicio: inicio)

        // Get the new view controller using segue.destinationViewController.
        // Pass the selected object to the new view controller.
    }

    //MARK: METODOS PRIVADOS

    private func actualizaEstadoBotonGuardar() {
        //DESHABILITA EL BOTON DE GUARDAR CUANDO ESTA EN BLANCO *WIP*
        let texto = nombreCalendario.text ?? ""
        let tieneTexto = !texto.isEmpty

        //WIP
        if (!texto.isEmpty) {
            if (fechaInicioCalendario.date >= fechaFinCalendario.date) {
                botonGuardar.isEnabled = false
            } else {
                botonGuardar.isEnabled = true
            }
        }
    }

}

【问题讨论】:

  • 您似乎有一个错字。 ViewController 而不是 ViewController1
  • 您要传递[Calendario] 对象还是只传递totalCalendarios var??
  • 仅总日历
  • @MartinHernandezPerez 在下面看到我的编辑。

标签: ios swift viewcontroller


【解决方案1】:

让我知道我哪里错了,你的代码让我有点困惑。 (我会编辑。)

您的totalCalendarios1ViewController1 实例中的一个值。在我看来,您希望将此值传递给 ViewController2,并传递给一个名为 totalCalendarios2 的变量。

首先,你有一个(小)错误:

let totalCalendarios2 = copiaCalendarios.totalCalendarios

不应该是totalCalendarios1吗? (这就是我对您的命名约定感到困惑的地方。希望这是语言问题,或者您将代码简化到打错字的程度。)

无论如何,这是一个小问题。 真正的问题在于您的 segue 代码。这就是你要纠正的地方。


假设您有以下内容:

ViewController1:

var totalCalendarios:Int = 0

ViewController2

var totalCalendarios:Int = 0

现在在ViewController1 中,此变量已更新为不同的值,可能是 2017,并且您希望将此值传递给 ViewController2。你所需要的——只要你定义了一个 segue——就是:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "MySegueName" {
        if let vc = segue.destination as? ViewController2 {
            vc.totalCalendarios = totalCalendarios
        }
    }
}

与发布的代码相比,最大的错误是将目标 VC 转换为 ViewController 而不是 ViewController2。我看到了其他潜在问题,但您的变量匹配度不够,我无法知道它们是否也是问题。

总结:

  • 除非您不能简单地保持变量名称相同,否则在视图控制器之间命名相同是没有问题的。事实上,它可以帮助其他人理解您的代码。
  • 如果您使用 segue,则无需实例化任何视图控制器。但是你应该在prepare(for segue:)中正确cast目标VC。
  • 转换后,只需传递变量即可。

【讨论】:

  • 是的,我已经更正了代码,它是 totalCalendarios1,对不起,我会试试你的代码,谢谢 :D
【解决方案2】:

我假设您的班级名称是ViewController1,正如您所说。没关系。但是您是如何通过let totalCalendarios2 = copiaCalendarios.totalCalendarios 的呢?是错字还是您实际上在代码中写了这一行?应该是:

let totalCalendarios2 = copiaCalendarios.totalCalendarios1

如果你真的想将数据从一个屏幕传递到另一个屏幕(实际上是一个控制器到另一个控制器),请遵循:

  1. 在您的第一个视图控制器(从您要传递的位置)中,具有您要传递的数据类型的属性。对于您的情况:

    var totalCalendarios = 0
    

    现在根据您的需要更新此totalCalendarios

  2. 要使用 segue 传递数据,您需要在 Interface Builder 中添加一个 segue(从源控制器到目标控制器)并提供 @987654329 @ 一个名字。假设 CalenderSegue

  3. 在您的第二个视图控制器(您想要传递的位置)中,您需要拥有一个与您从第一个视图控制器传递的数据的确切类型相同的属性。在您的情况下,它是Int。所以在你的第二个视图控制器中声明一个属性:

    var totalCalendarios = 0
    
  4. 现在用这个

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let identifier = segue.identifier, identifier = "CalenderSegue" { 
            let destino = segue.destination as? CalendarioViewController // here you have to use the exact name of your Second View Controller instead of ViewController
            destino?.totalCalendarios = totalCalendarios
        }
    }
    

编辑:1

从您的CalendarioViewController 类中删除这些行(您不需要为您的CalendarioTableViewController 创建对象)

let copiaCalendarios = CalendarioTableViewController()
let totalCalendarios = copiaCalendarios.totalCalendarios

将此添加到CalendarioViewController

var totalCalendarios = 0

然后使用上面的prepare(for segue: UIStoryboardSegue, sender: Any?) 方法。

但是如果你只有一个 segue 并且你已经从 TableViewCellCalendarioViewController 然后你可以使用

override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 
    let destino = segue.destination as? CalendarioViewController // here you have to use the exact name of your Second View Controller instead of ViewController
    destino?.totalCalendarios = totalCalendarios
}

编辑:2

您可能对segue 有疑问。从您的TableViewCell 中删除所有segues,然后将它们添加回来。如果你不知道怎么做,看这个

【讨论】:

  • 是的,我已经更正了代码,它是 totalCalendarios1,对不起,我会试试你的代码,谢谢 :D
  • 我在 segue 代码段中添加了一个打印语句,它打印 var totalCalendarios,并显示 2(加载的日历总数),然后在 CalendarioViewController 的 viewDidLoad() 中打印了 totalCalendarios,它显示为 0 . 这是结果: Total Calendarios (segue): 2 Total Calendarios (CalendarioViewController): 0
  • @MartinHernandezPerez 你在你的destino?.totalCalendarios = totalCalendarios 方法中使用了destino?.totalCalendarios = totalCalendarios 吗??
  • 是的。我确实使用了确切的代码:override func prepare(for segue: UIStoryboardSegue, sender: Any?) { print("Total calendarios es: " + String(calendarios.count)) let destino = segue.destination as? CalendarioViewController // here you have to use the exact name of your Second View Controller instead of ViewController destino?.totalCalendarios = totalCalendarios }
  • 问题是你在这个方法中打印了calendarios.count。但是您发送的是totalCalendarios var。尝试在此处打印totalCalendarios
猜你喜欢
  • 1970-01-01
  • 2020-08-16
  • 1970-01-01
  • 2021-03-30
  • 1970-01-01
  • 2020-11-08
  • 1970-01-01
  • 2021-01-06
  • 1970-01-01
相关资源
最近更新 更多