()

2017-08-30 6 views
0

ユーザーがセルとsegues上(didSelectRowAtを使用して)タップしたとき、私は、SubMenuViewControllerでのtableViewを持って、私は次のUserInputViewControllerにそのセルを渡す必要があり、()

はここに私のコードです:私のperformSegueで、今

class SubMenuViewController: UIViewController { 

    //MARK: - Properties and outlets 

    var node: Node? 
    @IBOutlet weak var tableView: UITableView! 

    //MARK: - View controller methods 

    override func viewDidLoad() { 

     super.viewDidLoad() 

     self.navigationController?.isNavigationBarHidden = false 
     self.navigationItem.title = node?.value.rawValue 

     let nib = UINib(nibName: "SubMenuTableViewCell", bundle: nil) 
     tableView.register(nib, forCellReuseIdentifier: "SubMenuCell") 
    } 

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 
     if segue.identifier == "userInput" { 
      let vc = segue.destination as! UserInputViewController 
      let indexPath = sender as! IndexPath 
      vc.node = node?.childenNode[indexPath.row] 
     } 
    } 
} 

//MARK: UITableViewDataSource methods 

extension SubMenuViewController: UITableViewDataSource { 

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     return node!.childCount 
    } 

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

     let cell = tableView.dequeueReusableCell(withIdentifier: "SubMenuCell", for: indexPath) as! SubMenuTableViewCell 
     let desciptionModule = node?.childenNode[indexPath.row].value 

     let description = Modules.description(module: desciptionModule!) 

     cell.title.text = description.main 
     cell.subtitle.text = description.sub 

     return cell 
    } 
} 

//MARK: - UITableViewDelegate methods 

extension SubMenuViewController: UITableViewDelegate { 
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 
     return 68 
    } 

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

     tableView.deselectRow(at: indexPath, animated: true) 

     guard let selectedNode = node?.childenNode[indexPath.row] else { 
      return 
     } 

     if selectedNode.isLeaveNode() { 
      performSegue(withIdentifier: "userInput", sender: indexPath) 
     } else { 
      let subMenuViewController = self.storyboard!.instantiateViewController(withIdentifier: "subMenu") as! SubMenuViewController 
      subMenuViewController.node = selectedNode 
      //let subMenuViewController = SubMenuViewController(node: selectedNode) 
      self.navigationController?.pushViewController(subMenuViewController, animated: true) 
     } 
    } 
} 

、私は、送信者に私のindexPathに渡された、と私はprepareForSegueにそれを取り戻すことを期待すべきであるが、私はできません。どんな提案?

+0

を言っています! IndexPath'クラッシュ? –

+0

選択したインデックスパスをSubMenuViewController(セルが選択されている場合)のプロパティとして保存し、必要なときにいつでも使用します(prepareForSegueなど)。 –

+0

@ArtKirillovは回避策ですが、彼のアプローチは有効であり、正しく動作しなければなりません。私が間違っていると私を修正してください。 –

答えて

1

私の意見では、sender引数としてインデックスパス(またはsの「データ」をカウントし、他の値)を渡すために非常に良い方法ではありません

おかげ。その名前が示すように、メッセージを送信したオブジェクトを渡すことを意図しています(つまり、アクションメソッドと呼ばれます)。この場合、self(アクションメソッドが別のアクションメソッドを代わりに呼び出す場合は元の送信者を「中継」できます。オフトピックはここ)。

@sChaがコメントで親切に指摘したように、特にこの方法に関するアップルの文書は疑いの余地が残っているようです。パラメータ名の送信者は、ココアのタグ/アクションパターンに従うすべての制御アクションの均等な議論から明らかです。

私の提案:

var selectedIndexPath: IndexPath? 

... :私はにあなたのビューコントローラの財産におけるインデックスパスだと思うあなたが行うことができます

最高tableView(_:didSelectRowAt:)に設定します。

if selectedNode.isLeaveNode() { 
    self.selectedIndexPath = indexPath 
    performSegue(withIdentifier: "userInput", sender: indexPath) 
} else { 
    self.selectedIndexPath = nil 
    // ... 

...とは、ターゲット・ビュー・コントローラのprepareForSegue(_:sender:)実装では(とそれをリセット)それをretieve:あなたは、この行は、 `indexPathは=送信者としましょうということ

if let vc = segue.source as? SubmenuViewController { 
    if let indexPath = vc.selectedIndexPath { 
     vc.selectedIndexPath = nil // (reset it, just to be safe) 

     // Use indexPath... 
    }  
} 
+1

私は '送付者 'を使うのは悪い習慣だとは思わない。 Appleのdocsは、この 'sender'を次のように説明しています:**あなたがsegueを開始するために使用したいオブジェクト。このオブジェクトは、実際のセグの情報のために利用できます。**セグを開始したい情報を送信することができます。 – sCha

+0

それを指摘していただきありがとうございます。 "segueをintiateするための使用"の部分は、私が言ったことを正確に再確認しているようです。「オブジェクトは情報提供の目的で提供されています」という部分はあいまいですが、私は同意します。「情報」が何であるかによって異なります。いずれにせよ、私はすべての**制御**アクションに共通する歴史的な送信者の議論(私は、 'prepareForSegue()'の場合でも名前がどこに来るのか)に沿って発言しました –