ios - 在Swift中的 View Controller 之间传递数据(从TableView到DetailViewController)

标签 ios swift uiviewcontroller tableview segue

我有两个文件,MyTableViewController和myViewController。我在MyTableVIewController中的TableCell上设置了UIImageView。 myViewController不包含任何内容。我创建了一个名为ImageArray的数组,其中包含一个Images数组。

我的目的是在myTableViewController中的TableCell上单击图像时,希望单击的图像出现在myViewController中。以及有关图像旁边单击的图像的一些描述。我想为用户使用myViewController以获得所选图像的详细信息。

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell") as! UITableViewCell
    var ImageView = cell.viewWithTag(1) as! UIImageView
    ImageView.image = UIImage(named: ImageArray[indexPath.row])
    ImageView.contentMode = .ScaleAspectFit

    var TextView = cell.viewWithTag(2) as! UILabel
    TextView.text = ImageArray[indexPath.row]
    return cell
}

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    performSegueWithIdentifier("next", sender: indexPath)
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if (segue.identifier == "next") {
        let destination = segue.destinationViewController as! myViewController
    }
}

我不知道该怎么做才能实现这一目标。如果您能帮助我解决问题,我将不胜感激!谢谢!

最佳答案

首先,我假设您的MyTableViewController类同时符合UITableViewDataSource和UITableViewDelegate协议,并且已将MyTableViewController类设置为代码中或通过Storyboard的委托。

解决了这些问题之后,有多种方法可以实现您想要的结果。
您可以在一个独立的类中声明ImageArray,并在MyTableViewController类中对其进行调用,使用tableView委托方法将它们索引到tableView上,最后使用prepareForSegue方法将图像推送到myViewController上。或者,您可以简单地在MyTableViewController类的顶部声明并初始化ImageArray,如下所示:

var ImageArray = [("Moscow Russia.jpg", "Europe"),
    ("London England.jpg", "Europe")]  

在上方的ImageArray中,确保您的图像名称与您导入到Xcode项目中的资产名称完全匹配。

然后我们使用以下所需方法指定需要ImageArray在tableView中占据多少行(即,基本上将ImageArray计入TableView中):
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
    return ImageArray.count ?? 0
}

接下来,您要使用tableView:cellForRowAtIndexPath:方法在单元格的每一行中显示ImageArray。

TabletCell上的旁注:希望您的TableCell是UITableViewCell的子类,并且您已经声明并连接了两个IBOutlet,分别是imageView和textLabel。另外,请确保TableCell已正确链接到Storyboard中的原型单元,位于 Identity Inspector 之下)。TableCell类应如下所示:
import UIKit
class CustomTableViewCell: UITableViewCell {
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var textLabel: UILabel!
}

现在回到MyTableVIewController类。从您的代码中,我看到您将'let cell = ...'行强制转换为'UITableViewCell。您应该将其强制转换为“TableCell”,因为您将其子类化。如下实现tableView:cellForRowAtIndexPath:方法:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{        
    let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell") as! TableCell

//Note that I'm using tuples here. Pretty cool huh. Got to love Swift!
  let (imageName, textNameToGoWithImage) = ImageArray[indexPath.row]

    cell.textLabel.text = textNameToGoWithImage
    cell.imageView.image = UIImage(named: imageName)
    cell.imageView.contentMode = .ScaleAspectFit

// You could have also used 'if let' in optional binding to safely unwrap your image if you want like below.
   //    if let image = UIImage(named: imageName){
   //        cell.imageView?.image = image
  //         cell.imageView.contentMode = .ScaleAspectFit
  //     }

    return cell
}

您似乎对何时何地使用 performSegueWithIdentifier 方法有点困惑,而不是使用- prepareForSegue 方法。甚至何时使用 tableView:didSelectRowAtIndexPath方法

让我在这里简单地解释一下。当您不控制将故事片段从一个ViewController的场景拖到情节提要中的另一个场景时,可以使用 performSegueWithIdentifier 方法。这样,只要您在 Attributes Inspector下的Storyboard中指定正确的标识符,使用 perform performSegueWithIdentifier 方法将允许您在ViewController场景之间移动。 '

现在,如果您使用的是Storyboard,则不需要 tableView:didSelectRowAtIndexPath 方法。 tableView:didSelectRowAtIndexPath 方法的作用是,它告诉委托人现在已选择了指定的行,并且我们可以在其代码体内执行某些操作(例如,将图像或文本推到另一个ViewController场景中,就像您尝试做的那样) )。但这在使用segues时变得多余。您所需要做的就是将MyTableViewController场景中的表格单元格中的 segue 拖放到myViewController场景中。选择“显示”,并为 segue 提供一个标识符名称,就像您完成“下一步”一样。 (一点注意事项:如果您希望在运行应用程序时将 Back 按钮功能显示在顶部导航栏,则只需将MyTableViewController嵌入UINavigationController中,即可为您提供 Back 按钮功能。您在情节提要中选择的MyTableViewController场景,请转到顶部菜单,然后选择编辑器>>嵌入>>导航控制器。然后单击Walla !!)

现在,让我们继续实现 tableView:prepareForSegue 方法,如下所示:
 override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "next" {
        //Note that, originally, destinationViewController is of Type UIViewController and has to be casted as myViewController instead since that's the ViewController we trying to go to. 
        let destinationVC = segue.destinationViewController as! myViewController


        if let indexPath = self.tableView.indexPathForSelectedRow{

            let selectedRow = ImageArray[indexPath.row]

            destinationVC.imageName2 = selectedRow.0
            destinationVC.textName2 = selectedRow.1
}

从上面的代码中,请确保首先使用myViewController类中的属性“imageName”和“textName”设置属性,然后才能使用现在为myViewController类型的“destinationVC”访问它们。这两个属性将保存我们从MyTableViewController类传递到myViewController类的数据。并且我们使用数组索引将数据相应地传递给这两个属性。

然后,您可以通过将这些设置的“imageName2”和“textName2”属性传递到出口(或与此相关的任何UI控件)来创建两个IBOutlet,以显示图像和文本。
  • 现在,您必须首先在其中设置属性的原因
    myViewController类,然后再传递它们(即传递给
    UI元素,闭包,另一个VC等)是,当您从
    MyTableViewController场景可以锁定到您的下一个ViewController
    场景(即您的myViewController场景),iOS尚未实例化
    第二个场景呢。因此,您需要一个属性来保存数据
    您正在尝试先传递到第二个场景View Controller,以便您可以
    稍后在该类最终加载时使用它。

  • 因此,您的myViewController类应如下所示:
    import UIKit
    
    class myViewController : UIViewController {
    
       //Your two strings to initially hold onto the data 
      //being passed to myViewController class
    var imageName2 : String?
    var textName2 : String?
    
    @IBOutlet weak var detailImageView: UIImageView!
    @IBOutlet weak var detailTextNameLabel: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        detailTextNameLabel.text = textName2!
    
        if let image = UIImage(named: imageName2!) {
            self.detailImageView.image = image
        }
    }
    

    就是这样!

    关于Swift中的标签和约定的注意事项:
  • 开始使用大写字母命名类(即class
    ViewController(){})
  • 类和属性应捕获它们的含义
    代表。我建议您更改MyTableViewController
    和“myViewController”类相应地反映它们真正的含义
    意思是或做(您可以使用“MainTableViewController”和“DetailViewController”。这样做就可以了)。
  • 对属性和方法使用camelToe标签。 (我用了你的标签
    为了避免让您感到困惑而在您的问题中提供)。

    请享用!
  • 关于ios - 在Swift中的 View Controller 之间传递数据(从TableView到DetailViewController),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33643752/

    相关文章:

    ios - UISearchBar resignFirstResponder 不工作

    ios - 数据传递失败

    ios - Cocoa - 安排定时任务来获取数据

    ios - UIScrollView 在自动布局中尺寸不正确

    ios - 如何在我的 NSXMLParser 中实现此方法来提取图像

    ios - 自定义TextField在SwiftUI代码中的VStack中不起作用

    swift - 标签栏 View Controller [Swift 3.0 - Xcode]

    ios - 切换选项卡后 UIViewcontroller 消失 UITabBarController

    ios - Xcode 多线程违规“留给我们的就是荣誉 cocoa ”

    ios - Xcode Swift - iOS 10 和 iOS 9 文本大小问题