【问题标题】:Swift: Pass UITableViewCell label to new ViewControllerSwift:将 UITableViewCell 标签传递给新的 ViewController
【发布时间】:2015-04-03 14:33:06
【问题描述】:

我有一个 UITableView,它使用基于 JSON 调用的数据填充单元格。像这样:

var items = ["Loading..."]
var indexValue = 0

// Here is SwiftyJSON code //

for (index, item) in enumerate(json) {
    var indvItem = json[index]["Brand"]["Name"].stringValue
    self.items.insert(indvItem, atIndex: indexValue)
    indexValue++
}
self.tableView.reloadData()

如何在单元格被选中时获取它的标签,然后将其传递给另一个 ViewController?

我设法得到:

func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
    println("You selected cell #\(indexPath.row)!")

    // Get Cell Label
    let indexPath = tableView.indexPathForSelectedRow();
    let currentCell = tableView.cellForRowAtIndexPath(indexPath!) as UITableViewCell!;

    println(currentCell.textLabel.text)
}

我只是不知道如何将它作为变量传递给下一个 UIViewController。

谢谢

【问题讨论】:

  • @DharmeshKheni 是的,我在以前的控制器上使用过它 - 我不知道如何在单击之前将带有标签测试的变量传递给 prepareForSegue,甚至对于 performSegue 启动。

标签: uitableview swift uiviewcontroller segue


【解决方案1】:

我是这样做的。

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

 let selectedName = nameArray[indexPath.row]      

let newView: nextViewName = self.storyboard?.instantiateViewController(withIdentifier: "nextViewName") as! nextViewName

   newView.label.text = selectedValue
   self.present(newView, animated: true, completion: nil)



}

【讨论】:

    【解决方案2】:

    你问:

    如何在单元格被选中时获取标签,然后将其传递给另一个 ViewController?

    我可能建议将问题改写如下:“如何检索与所选单元格关联的数据并将其传递给另一个视图控制器?”

    这听起来可能是一回事,但这里有一个重要的概念区别。您真的不想从单元格标签中检索值。我们的应用程序采用MVC 范式,因此当您想要将数据信息从一个场景传递到另一个场景时,您想要返回到模型(items 数组),而不是视图(text 的属性UILabel)。

    这是一个微不足道的例子,所以这种区分有点学术,但随着应用程序变得越来越复杂,这种回归模型的模式变得越来越重要。来自单元的字符串表示通常不能很好地替代实际模型对象。而且,正如您将在下面看到的,从模型中检索数据同样容易(如果不是更容易的话),所以您应该这样做。

    顺便说一句,在这种情况下,您根本不需要 didSelectRowAtIndexPath 方法。您所需要的只是从表格视图单元到目标场景的转场,给转场一个唯一标识符(在我的示例中为Details),然后实现prepare(for:sender:)

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let destination = segue.destination as? DetailsViewController {
            let selectedRow = tableView.indexPathForSelectedRow!.row
            destination.selectedValue = items[selectedRow]
        }
    }
    

    或者,如果您的转场在单元格和目标场景之间,您也可以使用prepare(for:sender:)sender

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let destination = segue.destination as? DetailsViewController {
            let cell = sender as! UITableViewCell
            let selectedRow = tableView.indexPath(for: cell)!.row
            destination.selectedValue = items[selectedRow]
        }
    }
    

    但想法是一样的。确定选择了哪一行,并从模型中检索信息,items 数组。

    以上是 Swift 3。对于 Swift 2.3,请看这个答案的previous version

    【讨论】:

    • 这个答案给了我我需要的帮助,即使我使用的是 Swift 3。我在发送控制器的 prepareForSegue 中缺少“let selectedRow”行(Swift 3 prepare(for segue:)) func 仅从所选单元格中获取数据。非常感谢罗!
    【解决方案3】:

    好的..我已经 2 天了,我一直在寻找答案,我如何能够保存选定的 UITableViewCell 标签文本数据并将该数据显示到另一个视图控制器上的另一个标签上,点击后会出现一个细胞。最后我完成了任务并且成功了。这是使用 Swift 的完整代码。我使用的是 Xcode 6.4。

    第 1 步。

    我有两个类分配给故事板视图控制器,名为“iOSTableViewControllerClass.swift”,它是一个表视图控制器和“iOSTutorialsViewControllerClass.swift”,它是一个普通视图控制器。

    第 2 步。

    现在,通过在情节提要区域上按住 Control 并拖动,从 iOSTableViewControllerClass 转到 iOSTutorialsViewControllerClass 并从下拉菜单中选择“显示”。根据下图点击这个突出显示的按钮并执行segue。

    第 3 步。

    现在通过单击情节提要选择转场,并在属性检查器上为其指定一个标识符。在这种情况下,我将其命名为“iOSTutorials”

    第 4 步。

    现在在这一步中,在您的单元格以及其他视图控制器上放置一个标签,并在它们相应的类上制作它们的出口。 在我的情况下,这些是“@IBOutlet weak var iOSCellLbl: UILabel!”和“@IBOutlet weak var iOSTutsClassLbl: UILabel!”。

    第 5 步。

    在第一个表视图控制器类上创建一个字符串类型变量。我这样做是因为“var sendSelectedData = NSString()”还在第二个类上创建了一个字符串类型变量。我这样做是“var SecondArray:String!”。

    第 6 步。

    现在我们准备好了。 这是头等舱的完整代码——

     // iOSTableViewControllerClass.swift
    
      import UIKit
    
      class iOSTableViewControllerClass: UITableViewController, UITableViewDataSource,UITableViewDelegate {
    
      // Creating A variable to save the text from the selected label and send it to the next view controller
    
      var sendSelectedData = NSString()
    
     //This is the outlet of the label but in my case I am using a fully customized cell so it is actually declared on a different class
    @IBOutlet weak var iOSCellLbl: UILabel!
    
    //Array for data to display on the Table View
    var iOSTableData = ["Label", "Button", "Text Field", "Slider", "Switch"];
    override func viewDidLoad() {
        super.viewDidLoad()
    
    //Setting the delegate and datasource of the table view
    
        tableView.delegate = self
        tableView.dataSource = self
    
    //Registering the class here
        tableView.registerClass(CustomTableViewCellClassiOS.self, forCellReuseIdentifier: "CellIDiOS")
    
    //If your using a custom designed Cell then use this commented line to register the nib.
        //tableView.registerNib(UINib(nibName: "CellForiOS", bundle: nil), forCellReuseIdentifier: "CellIDiOS")
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    // MARK: - Table view data source
    
    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        // Return the number of sections.
        return 1
    }
    
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // Return the number of rows in the section.
        return iOSTableData.count
    }
    
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let CellIDentifier = "CellIDiOS"
    
     //In this case I have custom designed cells so here "CustomTableViewCellClassiOS" is the class name of the cell
        var cell:CustomTableViewCellClassiOS! = tableView.dequeueReusableCellWithIdentifier(CellIDentifier, forIndexPath: indexPath) as? CustomTableViewCellClassiOS
        if cell == nil{
            tableView.registerNib(UINib(nibName: "CellForiOS", bundle: nil), forCellReuseIdentifier: CellIDentifier)
            cell = tableView.dequeueReusableCellWithIdentifier(CellIDentifier) as? CustomTableViewCellClassiOS
    
        }
     //Here we are displaying the data to the cell label
        cell.iOSCellLbl?.text = iOSTableData[indexPath.row]
        return cell
    }
    
    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    
        println("You selected cell #\(indexPath.row)!")
    
        // Get Cell Label text here and storing it to the variable
        let indexPathVal: NSIndexPath = tableView.indexPathForSelectedRow()!
        println("\(indexPathVal)")
        let currentCell = tableView.cellForRowAtIndexPath(indexPathVal) as! CustomTableViewCellClassiOS!;
        println("\(currentCell)")
        println("\(currentCell.iOSCellLbl?.text!)")
        //Storing the data to a string from the selected cell
        sendSelectedData = currentCell.iOSCellLbl.text!
        println(sendSelectedData)
    //Now here I am performing the segue action after cell selection to the other view controller by using the segue Identifier Name
        self.performSegueWithIdentifier("iOSTutorials", sender: self)
    }
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    
    //Here i am checking the Segue and Saving the data to an array on the next view Controller also sending it to the next view COntroller
        if segue.identifier == "iOSTutorials"{
    //Creating an object of the second View controller
            let controller = segue.destinationViewController as! iOSTutorialsViewControllerClass
    //Sending the data here
            controller.SecondArray = sendSelectedData as! String
    
     }
    

    这是第二个类的完整代码..--

    //  iOSTutorialsViewControllerClass.swift
    
    import UIKit
    
    class iOSTutorialsViewControllerClass: UIViewController {
    
    //Creating the Outlet for the Second Label on the Second View Controller Class
    @IBOutlet weak var iOSTutsClassLbl: UILabel!
    
    //Creating an array which will get the value from the first Table View Controller Class
    var SecondArray:String!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
    //Simply giving the value of the array to the newly created label's text on the second view controller
       iOSTutsClassLbl.text = SecondArray
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    }
    

    【讨论】:

      【解决方案4】:

      在两个视图控制器之间传递数据取决于视图控制器如何相互链接。如果它们与 segue 链接,则需要使用 performSegueWithIdentifier 方法并覆盖 prepareForSegue 方法

      var valueToPass:String!
      
      func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
          println("You selected cell #\(indexPath.row)!")
      
          // Get Cell Label
          let indexPath = tableView.indexPathForSelectedRow();
          let currentCell = tableView.cellForRowAtIndexPath(indexPath!) as UITableViewCell!;
      
          valueToPass = currentCell.textLabel.text
          performSegueWithIdentifier("yourSegueIdentifer", sender: self)
      
      }
      
      override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
      
          if (segue.identifier == "yourSegueIdentifer") {
      
              // initialize new view controller and cast it as your view controller
              var viewController = segue.destinationViewController as AnotherViewController
              // your new view controller should have property that will store passed value
              viewController.passedValue = valueToPass
          }
      
      }
      

      如果您的视图控制器没有与 segue 链接,那么您可以直接从 tableView 函数传递值

      func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
          println("You selected cell #\(indexPath.row)!")
      
          // Get Cell Label
          let indexPath = tableView.indexPathForSelectedRow();
          let currentCell = tableView.cellForRowAtIndexPath(indexPath!) as UITableViewCell!;
          let storyboard = UIStoryboard(name: "YourStoryBoardFileName", bundle: nil)
          var viewController = storyboard.instantiateViewControllerWithIdentifier("viewControllerIdentifer") as AnotherViewController
          viewController.passedValue = currentCell.textLabel.text
          self.presentViewController(viewContoller, animated: true , completion: nil) 
      }
      

      【讨论】:

      • 您如何从 didSelectRowAtIndexPath 访问“valueToPass”来 prepareForSegue?它绝对无法访问标识符,因为它们是不同的功能。 didSelectRowAtIndexPath 内部的变量被 {} 覆盖,无法在函数外部访问。
      • @jefferyleo 我的回答涵盖了两种不同的场景,并且它们彼此没有关联。 valueToPass 属于第一种场景(其中 vc 与 segue 连接),didSelectRowAtIndexPath 是秒场景
      • viewController.passedValue = currentCell.textLabel.text' .passedValue 不再存在了吗? ://
      • 出于某种奇怪的原因,我的数据总是在第二次点击时传递。
      • @V1P3R 请注意使用didSelectRowAtIndexPath 而不是didDeselectRowAtIndexPath 。如果您没有注意到区别在于选择和取消选择
      猜你喜欢
      • 1970-01-01
      • 2016-02-04
      • 1970-01-01
      • 2013-09-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多