web-dev-qa-db-ja.com

SwiftのUITableViewCellからViewControllerにセグエをプッシュする

UITableViewCellsで問題が発生しています。 UITableViewをAPIに接続して、セルにデータを入力しました。

次に、_indexPath.row_を取得して、RestaurantViewControllerに送信する必要がある配列内のJSONオブジェクトを識別する関数を作成しました。

デバッグと問題解決を容易にするためのXcodeプロジェクトへのリンク

これが、小さなスニペットが「行クリック」をグローバル変数に設定する方法です。

_func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
     i = indexPath.row
}
_

そして、ここに私のprepareForSegue()関数があります。これは私のプッシュセグエをRestaurantViewControllerに接続する必要があります。

_override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if segue.identifier == "toRestaurant"{
    let navigationController = segue.destinationViewController as UINavigationController
    let vc = navigationController.topViewController as RestaurantViewController
    vc.data = currentResponse[i] as NSArray
 }
}
_

そして、これがUITableViewCellからセグエを設定する方法です 

これが私の結果です。これらのセルを1つずつクリックしようとしましたが、別のviewControllerにプッシュされません...エラーも発生しません。ここで何が問題になっていますか?

機能しないソリューションを試しました

_override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
        if segue.identifier == "toRestaurant"{
            let vc = segue.destinationViewController as RestaurantViewController
            //let vc = navigationController.topViewController as RestaurantViewController
            vc.data = currentResponse[i] as NSArray
        }
    }
_
12
Jack

問題は、データを正しく処理していないことです。 currentResponse配列を調べると、NSDictionariesが保持されていることがわかりますが、prepareForSegueでNSDictionaryをNSArrayにキャストしようとすると、アプリがクラッシュします。

dataRestaurantViewController変数をNSDictionaryに変更し、prepareForSegueを変更してNSDictionaryを渡す

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if let cell = sender as? UITableViewCell {
        let i = redditListTableView.indexPathForCell(cell)!.row
        if segue.identifier == "toRestaurant" {
            let vc = segue.destinationViewController as RestaurantViewController
            vc.data = currentResponse[i] as NSDictionary
        }
    }
}
20
ergoon

次の手順で問題を解決できます。そうでない場合は、お知らせください。

  1. tableView(tableView, didSelectRowAtIndexPath:)実装を削除します。

  2. dataRestaurantViewControllerの型をNSDictionary!にします

  3. prepareForSegueで選択されている行を特定します。

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
        if let cell = sender as? UITableViewCell {
            let i = tableView.indexPathForCell(cell)!.row
            if segue.identifier == "toRestaurant" {
                let vc = segue.destinationViewController as RestaurantViewController
                vc.data = currentResponse[i] as NSDictionary
            }
        }
    }
    
4
Tammo Freese

Dropboxのstack3ディレクトリへのリンク

  1. ソフトウェアが標準の2レベルのテーブルビュー構造と大きく異なる理由を理解できません。そこで、このリンクからアクセスできる短い例をコーディングしました。以下のソースコードも含めました。

  2. プログラムはあなたが持っているものを模倣しています(私が理解している限り)。テーブルコントローラー1は、テーブルビューセルからテーブルコントローラー2にセグエします。セグエイングに問題はありませんでした。セグエを開始するためにストーリーブックを拡張する必要がないことを確認してください。

  3. 両方のコントローラーをナビゲーションコントローラーに埋め込みました。私の経験では、ナビゲーションを設定するための多くの労力が節約されます。

  4. または、画面上部の最初のTableViewControllerシンボルから2番目のコントローラーまでコントロールをドラッグして、セグエを設定することもできます。

  5. 推奨される方法ではありませんが、グローバル変数(selectedRow)を使用しました。しかし、prepareForSegueを使用してRestaurantTableViewControllerに変数を設定するのと同じくらい簡単です(例を示します)。

    1. 最後に、接続インスペクター(最初のコントローラーのテーブルビューセル)をチェックして、2番目のコントローラーにセグエがあることを確認することをお勧めします。コントロールを適切にドラッグすると、確認プロンプトと接続インスペクタのエントリが表示されます。

残念ながら、コードを適切にフォーマッターで取得できません

import UIKit

var selectedRow = -1

class TableViewController: UITableViewController {

var firstArray = ["Item1","Item2","Item3","Item4"]

override func viewDidLoad() {

super.viewDidLoad()

}

override func didReceiveMemoryWarning() {

super.didReceiveMemoryWarning()

}

// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {

return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

return firstArray.count

}


let nameOfCell = "RestaurantCell"

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

let cell = tableView.dequeueReusableCellWithIdentifier(nameOfCell, forIndexPath: indexPath) as UITableViewCell

cell.textLabel!.text = firstArray[indexPath.row]

return cell

}

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

selectedRow = indexPath.row

}

// MARK: - Navigation

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

let vc = segue.destinationViewController as RestaurantTableViewController

// can write to variables in RestaurantTableViewController if required

vc.someVariable = selectedRow

}


}


import UIKit

class RestaurantTableViewController: UITableViewController {

var secondArray = ["Item 2.1", "Item 2.2", "Item 2.3", "Item 2.4"]

var someVariable = -1

override func viewDidLoad() {

super.viewDidLoad()

}

override func didReceiveMemoryWarning() {

super.didReceiveMemoryWarning()

}

// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {

return 1

}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

return secondArray.count

}

let nameOfCell = "RestaurantCell"

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

let cell = tableView.dequeueReusableCellWithIdentifier(nameOfCell, forIndexPath: indexPath) as UITableViewCell

cell.textLabel!.text = secondArray[indexPath.row]

if indexPath.row == selectedRow {

cell.textLabel!.text = cell.textLabel!.text! + " SELECTED"

}

return cell

}

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

selectedRow = indexPath.row

}

}
3
Syed Tariq

ストーリーボードのスクリーンショットで、セグエが最初のプロトタイプセルをRestaurantViewControllerに接続していることに気付きました。このプロトタイプセルは、右側に開示インジケータアクセサリが付いた「基本」スタイルのセルのように見えます。ただし、実行中のアプリのスクリーンショットを見てください。テーブルには、右側に開示インジケータアクセサリがないセルの「サブタイトル」スタイルのように見えるセルが入力されています。

セグエが特定のプロトタイプセルに対してのみ機能するように構成されているにもかかわらず、セグエが実行されない理由は、テーブルにデータを入力するときにそのプロトタイプセルが使用されないためです。 _tableView:cellForRowAtIndexPath:_で何をしている場合でも、必要なプロトタイプセルを使用していません。

@Starscreamは、適切なセルを適切な識別子でデキューし、それをInterface Builderのプロトタイプセルの識別子と照合する適切なアイデアを持っています。それを行った後でも発生するクラッシュは、上記のコメントで述べた以前の問題が原因である可能性があります。ストーリーボードのセグエは明らかにUITableViewControllerを指しています。 RestaurantViewControllerUITableViewControllerのサブクラスである限り、_prepareForSegue:sender:_のコードは_let vc = segue.destinationViewController as RestaurantViewController_である必要があります。 UINavigationControllerとしてキャストしようとするとクラッシュします。また、ストーリーボードの宛先UITableViewControllerのクラスが、[Identity Inspector]ペインでRestaurantControllerとしてリストされていることを確認してください。ストーリーボードにジェネリックUITableViewControllerが含まれているだけでプログラムがコンパイルされるとクラッシュします。

元の問題にさらに戻ると、_tableView:cellForRowAtIndexPath:_をどのように実装したかわかりません。これは重要かもしれません。多分それはそれほど単純ではありません。おそらく、多くのプロトタイプセルを処理するか、実行時にカスタムセルを生成することを計画しています。この場合、これを簡単にする1つの方法は、ユーザーがセルをタップしたときにプログラムでセグエを実行することです。特定のプロトタイプセルを使用する代わりに、セグエを "Restaurangernäramig" UITableViewControllerからRestaurantViewControllerに向かう接続にしてください。 (Interface Builderで接続するには、最初のアイコンの上部にあるTable View Controllerアイコンから2番目の本体にドラッグしてControlキーを押しながらクリックします)。これを有効にするには、属性インスペクタペインでこのセグエに識別子を与える必要があります。 _"toRestaurant"_だとしましょう。次に、_tableView:didSelectRowAtIndexPath:_メソッドの最後に、次のコード行を挿入します:self.performSegueWithIdentifier("toRestaurant", sender: self)。テーブルで選択されているセルに関係なく、このセグエは常に起動します。

2

私は今Swiftに入っているのでここで気まぐれに出かけますが、prepareForSegue()でそれを行う方法は次のようなものです:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if segue.identifier == "toRestaurant"{
        let navigationController = segue.destinationViewController as UINavigationController
        let vc = navigationController.topViewController as RestaurantViewController
        //notice I changed [i] to [index!.row]
        vc.data = currentResponse[index!.row] as NSArray
     }
    }

私には、クラスのメソッド内のプライベート変数のようなi変数を呼び出しているように見えます。 @Syed TariqがselectRow変数を使用して行ったようなことを実行し、class SomeController: UIViewController /*, maybe some more here? */ {の上に設定して、変数を内部で署名できます。

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    selectedRow = indexPath.row

}

上記のような方法ですが、どちらの方法もかなりうまくいくはずです。

1
KyleMassacre

cellForRowメソッドで次のようなセルを作成してみてください:

let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier("MyTestCell", forIndexPath: indexPath)
1
Starscream

私は同じ問題を抱えていましたが、解決策は次のとおりです:

performSegueWithIdentifier( "toViewDetails"、sender:self)

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    var cellnumber = procMgr.processos[indexPath.row].numero
    println("You selected cell #\(indexPath.row)")
    println(cellnumber)
    performSegueWithIdentifier("toViewDetails", sender: self)
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "toViewDetails" {
         let DestViewController : ViewDetails = segue.destinationViewController as! ViewDetails
    }
}
0
João Henrique

UItableviewの選択されたセルインデックスを取得する必要がある場合があります。以下のコードは、選択されたセルインデックス(UItableview.indexPathForSelectedRow)を使用して、配列の正しい要素を取得しました。

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if segue.identifier == "seguaVisitCardDetial" {
        let viewController = segue.destinationViewController as! VCVisitCardDetial
        viewController.dataThisCard =   self.listOfVisitCards[(tblCardList.indexPathForSelectedRow?.row)!]
    }
}
0
Chamath Jeevan