簡體   English   中英

在Swift中從視圖控制器之間傳遞數據(從TableView到DetailViewController)

[英]Passing data between View Controllers in Swift (From TableView to DetailViewController)

我有兩個文件,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類符合UITableViewDataSourceUITableViewDelegate協議,並且您已將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

您的TableCell側面說明:希望您的TableCell的是從子類的UITableViewCell,並且您已經申報並分別連接的兩個IBOutlets,也就是說,imageview的並且為textLabel。 此外,確保您的TableCell正確地鏈接到Identity Inspector下的Storyboard中的原型單元格。您的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方法

我在這里簡單解釋一下。 當您沒有控制時,可以使用performSegueWithIdentifier方法 - 將一個ViewController的場景中的segue拖動到Storyboard中的另一個場景。 這樣,只要您在“ 屬性檢查器 ”下的“故事板”中指定了正確的標識符,使用performSegueWithIdentifier方法就可以在ViewController場景之間移動

現在,如果您使用的是Storyboard,則不需要tableView:didSelectRowAtIndexPath方法。 tableView:didSelectRowAtIndexPath方法的作用是告訴委托現在選擇了指定的行,我們可以在其代碼體內執行某些操作(例如將圖像或文本推送到另一個ViewController場景,就像您嘗試做的那樣)。 但是當你使用segues時,這就變得多余了。 您所要做的就是控制 - 將您的MyTableViewController場景中的表格單元格中segue 拖動myViewController場景。 選擇“ 顯示 ”並為segue指定一個標識符名稱,就像你“ 下一步 ”一樣。 小邊注:如果你想后退按鈕的功能,在頂部導航欄,當你運行你的應用程序中顯示,只需嵌入您MyTableViewController在一個UINavigationController給你,“ 后退 ”按鈕功能與您的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 '設置為屬性 ,然后才能使用' destinationVC '訪問它們,而' destinationVC現在是myViewController類型。 這兩個屬性將保存我們從MyTableViewController類傳遞到myViewController類的數據。 我們正在使用數組索引相應地將數據傳遞給這兩個屬性。

然后,您可以通過將這些設置' imageName2 '和' textName2 '屬性傳遞到您的出口(或任何UI控件)來創建兩個IBOutlet來顯示您的圖像和文本。

  • 現在為什么你會有你把它們或周圍之前先設置在myViewController類屬性的原因(即UI元素,關閉,另一個VC等)的是,當你從MyTableViewController場面創下的tableView細胞Segue公司到您的下一個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中標簽和約定的注意事項:

  • 用塊字母開始命名類(即類ViewController(){})
  • 類和屬性應該捕獲它們所代表的含義。 我建議您相應地更改MyTableViewController和' myViewController '類以反映它們的真正含義或做什么(您可以使用'MainTableViewController'和'DetailViewController'。這樣做會很好)。
  • 使用camelToe標簽來表示屬性和方法。 (我使用了你在問題中提供的標簽,以免過多地混淆你)。

    請享用!

這應該有助於:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if (segue.identifier == "next") {
        let destination = segue.destinationViewController as! myViewController
        destination.imageView.image = UIImage(named: ImageArray[tableView.indexPathForSelectedRow?.row])
        destination.textView.text = ImageArray[tableView.indexPathForSelectedRow?.row]
    }

}

(imageView和textView是新viewController中的視圖。)

注意:

  1. tableView.indexPathForSelectedRow?.row應該給你所選擇的行,顧名思義,但它可以是nil ,所以要小心。
  2. 另外,Swift變量命名約定是camelCase,因此imageView是正確的方法,而ImageView是不正確的。

在swift 3中,您可以執行以下操作:

MyTableViewController類中:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! UITableViewCell

    // for imageview

    var ImageView : UIImageView = cell.contentView.viewWithTag(1) as! UIImageView
    ImageView.image = UIImage(named: ImageArray[indexPath.row])


    // for text

    var TextView : UILabel = cell.contentView.viewWithTag(2) as! UILabel
    ImageView.text = ImageArray[indexPath.row]

    return cell
}

在你的didSelectRow方法中:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
   let nextVC = self.storyboard?.instantiateViewController(withIdentifier: "myViewController") as! myViewController
   nextVC.myImgView.image = UIImame(named: ImageArray[indexPath.row])
   nextVC.myLabel.text = ImageArray[indexPath.row]
   self.present(nextVC!, animated: true)
}

myViewController類中:

class myViewController: UIViewController
{
    let myImageView = UIImageView()
    let myLabel = UILabel()
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM