简体   繁体   English

将数据(标签)从TableViewCell传递到另一个ViewController

[英]Pass Data (Label) from TableViewCell to another ViewController

I want to pass the Label from a TableViewCell to a ViewController when I click on the Cell. 我想在单击单元格时将Label从TableViewCell传递给ViewController。 In the end it should be like twitter, that if you click on a cell with a Label you get passed on a detailViewController with the same Label init. 最后,它应该类似于twitter,如果您单击带有Label的单元格,则将传递带有相同Label初始化的detailViewController。 My Code doesn't work as I just get the blanket Label from the Storyboard... 我的代码不起作用,因为我只是从情节提要中获得了总括性的标签...

import UIKit
import Firebase

class JobTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

@IBOutlet weak var tableView: UITableView!
var valueToPass:String!


 func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
    return true
}

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

 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
    // Arvice return to count jobs
    return jobs.count
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    print("You selected cell #\(indexPath.row)!")

    // Get Cell Label
    let indexPath = tableView.indexPathForSelectedRow!
    let currentCell = tableView.cellForRow(at: indexPath)! as UITableViewCell

    let valueToPass = currentCell.textLabel?.text
    print("value: \(valueToPass)")

    performSegue(withIdentifier: "toDetails", sender: valueToPass)
}

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
    let cell = tableView.dequeueReusableCell(withIdentifier: "JobCell", for: indexPath) as! JobTableViewCell
    let job = jobs[indexPath.row]
    cell.job = job

    //spacing
    cell.contentView.backgroundColor = UIColor.clear

    let whiteRoundedView : UIView = UIView(frame: CGRect(x: 10, y: 8, width: self.view.frame.size.width - 20, height: 120))

    whiteRoundedView.layer.backgroundColor = CGColor(colorSpace: CGColorSpaceCreateDeviceRGB(), components: [0.36, 0.39, 0.40, 1.0])
    whiteRoundedView.layer.masksToBounds = false
    whiteRoundedView.layer.cornerRadius = 2.0
    whiteRoundedView.layer.shadowOffset = CGSize(width: 0, height: 0)
    whiteRoundedView.layer.shadowOpacity = 0.0

    cell.contentView.addSubview(whiteRoundedView)
    cell.contentView.sendSubview(toBack: whiteRoundedView)

    cell.emojiLabel.text = cell.emojiString

    return cell
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "toDetails" {
        let destinationViewController = segue.destination as! JobDetailViewController
        destinationViewController.valueToPass = (sender as? String)!
    }
}

My Cell: 我的手机:

import UIKit
import Firebase

class JobTableViewCell: UITableViewCell {

@IBOutlet weak var jobLabel: UILabel!

var job: Job! {
    didSet {
        jobLabel.text = job.text
    }
}
}

Job.Swift: Job.Swift:

import Foundation
import Firebase

class Job{

var text: String = ""
let ref: DatabaseReference!

init(text: String) {
    self.text = text
    ref = Database.database().reference().child("jobs").childByAutoId()
}

init(snapshot: DataSnapshot)
{
    ref = snapshot.ref
    if let value = snapshot.value as? [String : Any] {
        text = value["text"] as! String
    }
}

func save() {
    ref.setValue(toDictionary())
}

func toDictionary() -> [String : Any]
{
    return [
        "text" : text,
    ]
}
}

And in my DestinationController: 在我的DestinationController中:

import UIKit
import Firebase

class JobDetailViewController: UIViewController {

 @IBOutlet weak var jobDetail: RoundText!



var valueToPass: String = ""

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    jobDetail.text = valueToPass
}

override func viewDidLoad() {
    super.viewDidLoad()

    title = "Jobinformation"
}
}

You should not be using cells to store data. 您不应该使用单元格来存储数据。 You should have a data model that represents the data you are showing in the cells, and you should use the indexPath of the selected cell to look up the data in your data model. 您应该具有一个数据模型,该数据模型表示要在单元格中显示的数据,并且应该使用所选单元格的indexPath在数据模型中查找数据。

Quick solution: 快速解决方案:

  1. Change performSegue(withIdentifier: "yourSegueIdentifer", sender: self) to performSegue(withIdentifier: "yourSegueIdentifer", sender: valueToPass) performSegue(withIdentifier: "yourSegueIdentifer", sender: self)更改为performSegue(withIdentifier: "yourSegueIdentifer", sender: valueToPass)

2.Your prepare for Segue method should looks like this: 2.您准备Segue方法应如下所示:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
     if segue.identifier == "yourSegueIdentifer" {
         let destinationViewController = segue.destination as!   AnotherViewController
             destinationViewController.valueToPass = sender as? String
    }
}
  1. On AnotherViewController create var valuteToPass: String = "" and set your label.text = valueToPass 在AnotherViewController上创建var valuteToPass: String = ""并设置您的label.text = valueToPass

But I think you should not use currentCell.textLabel.text value, instead use the original value. 但我认为您不应使用currentCell.textLabel.text值,而应使用原始值。 (like if you set your currentCell as cell.textLabel.cell = array[indexPath.row] , your valueToPass should be valueToPass = array[indexPath.row] ) (就像您将currentCell设置为cell.textLabel.cell = array[indexPath.row] ,您的valueToPass应该是valueToPass = array[indexPath.row]

EDIT: 编辑:

You use didDeselectRowAt method, instead of didSelectRowAt. 您使用didDeselectRowAt方法,而不是didSelectRowAt。

Change func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) to func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath)更改为func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)

Don't use global variable, create it in didSelectRowAt. 不要使用全局变量,请在didSelectRowAt中创建它。

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    print("You selected cell #\(indexPath.row)!")

    // Get Cell Label
    let indexPath = tableView.indexPathForSelectedRow!
    let currentCell = tableView.cellForRow(at: indexPath)! as UITableViewCell

    let valueToPass = currentCell.textLabel?.text
    print("value: \(valuteToPass)")

    performSegue(withIdentifier: "toDetails", sender: valueToPass)
}

On DestinationController: 在DestinationController上:

class DestinationController: UIViewController {

var valuteToPass: String = ""

  override func viewDidLoad() {
    super.viewDidLoad()
   jobLabel.text = valueToPass
   }

}

EDIT2 编辑2

JobTableViewController JobTableViewController

  1. delete var valueToPass:String! 删除var valueToPass:String!

Change let valueToPass = jobs[indexPath.row].text instead of let valueToPass = currentCell.textLabel?.text I checked this change in your code, this will work. 更改let valueToPass = jobs[indexPath.row].text而不是let valueToPass = currentCell.textLabel?.text我在您的代码中检查了此更改,这将起作用。

Hi I cant comment but im using @Dris answer and I kept getting this error that says 嗨,我无法发表评论,但即时通讯使用@Dris答案,但我一直收到此错误消息

Could not cast value of type 'UITableViewCell' (0x115464e18) to 'NSString' (0x10fa594c8).

The SIGABRT targets the line destinationViewController.valueToPass = (sender as? String)! SIGABRT的目标行是destinationViewController.valueToPass = (sender as? String)!

Why is that? 这是为什么?

this is basically my code 这基本上是我的代码

 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        //  Determine what to do when a cell in a particular section is selected.
        print("did select:      \(indexPath.row)  ")

        // Get Cell Label
        let indexPath = tableView.indexPathForSelectedRow!
        let currentCell = tableView.cellForRow(at: indexPath)! as UITableViewCell

        valueToPass = currentCell.textLabel?.text
        print("valueToPass: \(String(describing: valueToPass))")
        performSegue(withIdentifier: "cellToView", sender: self)

    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        var cell:UITableViewCell?

        if tableView == self.tableView {

            let currentNotif = notificationList[indexPath.row]
            cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as UITableViewCell
            cell?.textLabel?.text = currentNotif.notifType
            cell?.detailTextLabel?.text = "\(currentNotif.notifTime) \n\(currentNotif.notifContent)"
        }

        if tableView == self.tableViewAnnounce {

            let currentAnnounce = announcementList[indexPath.row]
            cell = tableView.dequeueReusableCell(withIdentifier: "cellAnn", for: indexPath) as UITableViewCell
            cell?.textLabel?.text = currentAnnounce.annouceType
            cell?.detailTextLabel?.text = "\(currentAnnounce.annouceTime) \n\(currentAnnounce.annouceContent)"
        }

        return cell!

    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "cellToView" {
            // perform custom segue operation.

            let destinationViewController = segue.destination as! ExtendedAnnouncementViewController
            destinationViewController.valueToPass = (sender as? String)!
        }
    }

I'd avoid using a global variable to pass the data to the destination view controller. 我会避免使用全局变量将数据传递到目标视图控制器。 Defer the lookup until you are ready to pass the data. 推迟查找,直到准备好传递数据为止。

And, avoid using force unwrap, it leads to runtime crashes. 并且,避免使用强制解包,这会导致运行时崩溃。

Use something like this instead: 使用类似这样的东西:

let segueIdentifier = "yourSegueIdentifer"
let labelDataSource: [String] = ["SomeText"]

func label(forIndexPath indexPath: IndexPath) -> String? {
    let index = indexPath.row
    guard labelDataSource.indices.contains(index) else { return nil }

    return labelDataSource[index]
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    performSegue(withIdentifier: segueIdentifier, sender: indexPath)
}

func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    guard segue.identifier == segueIdentifier,
        let indexPath = sender as? IndexPath,
        let destinationViewController = segue.destination as? AnotherViewController else { return }

    destinationViewController.valuePassed = label(forIndexPath: indexPath)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM