web-dev-qa-db-ja.com

Swiftのuitableviewcellクラスからコントローラーを参照する方法

私は次のものを持っています

  1. ViewController
  2. tableView
  3. CustomCell

CustomCellクラスを使用するセルにNIB(.xibファイル)を使用しました。このカスタムセルクラスは、セルのボタンをタッチするためのIBActionを処理します。 ViewControllerとその中のいくつかの変数を参照したいと思います。どのようにそれを行うべきですか(ViewControllerにアクセスする)?

ありがとう!

33
Norly Canarias

セルとView Controllerの間にこの種の依存関係を作成することはしません。これにより、アーキテクチャがより複雑になり、セルが再利用できなくなります。

委任パターンを使用することをお勧めします。これは少し複雑に聞こえるかもしれません-既に使用している場合でも(UITableViewDelegateは典型的な例です):

  • 1つのメソッドMyCellProtocolでプロトコルdidTapCellを作成し、UITableViewCellおよび/またはView Controllerに渡すカスタムデータを受け入れます
  • カスタムセルにパブリックデリゲートプロパティを作成します:_weak var cellDelegate: MyCellProtocol?_
  • didTapXXXハンドラーまたはセルのdidSelectRowAtIndexPathで、self.cellDelegate?.didTapCell()を呼び出し、期待されるパラメーターを渡します
  • view Controllerで、MyCellProtocolを実装します
  • view ControllerのcellForRowAtIndexPathで、セルの作成/デキュー時に、そのcellDelegateプロパティをselfに設定します

この時点で、セルでタップが行われると、View ControllerのdidTapCellメソッドが呼び出され、そこから必要なことを実行できます。

重要な点は、セルにセルのタップ/選択を処理させるのではなく、View Controllerに通知してジョブを実行させることです。

47
Antonio
extension UIView {
    var parentViewController: UIViewController? {
        var parentResponder: UIResponder? = self
        while parentResponder != nil {
            parentResponder = parentResponder!.next
            if let viewController = parentResponder as? UIViewController {
                return viewController
            }
        }
        return nil
    }
}

セル内

if let myViewController = parentViewController as? MyViewController {
    print(myViewController.title)
}
19
Blank

私はあなたがそれをするべきではないと思います、おそらくあなたは何か間違ったことをしていると思いますが、本当に本当に必要な場合は、CustomCellクラスにプロパティがあります。

var viewController : UIViewController

次に、cellForRowAtIndexPathにセルを作成するときにプロパティを設定します

cell.viewController = self

その後、セルコード内からView Controllerに簡単にアクセスできます。

self.viewController.doSomething()

しかし、繰り返しますが、私の意見では、コードを再設計する必要があります。セルはコントローラーを気にするべきではありません。自分自身を表示するだけで、他には何も気にしない

13

拡張機能を追加

 extension UITableViewCell {

        var viewControllerForTableView : UIViewController?{
            return ((self.superview as? UITableView)?.delegate as? UIViewController)
        }

    }

以下のようにキャストします

   if let viewController = self.viewControllerForTableView as? AnyController{

       print(viewController.variable)

   } 

2
Gopal krishan

最善の方法は、委任を実装することです。デリゲートは、ボタンのクリックについてView Controllerに通知します。また、View Controller(上記のデリゲートのプロトコルに準拠している)がクリックイベントで実行するタスクを処理します。 (委任パターンのチュートリアルはオンラインで利用できます。委任の方法を知りたい場合は、それらを確認できます)。

2
Tejas

これを試す前に実際に代替アプローチを使用したいという他のコメントを読んでくださいが、この拡張機能を使用すると、dataSourceである必要があるdelegateおよびUITableViewControllerに到達できます

extension UITableViewCell {
    var tableView:UITableView? {
        get {
            for var view = self.superview ; view != nil ; view = view!.superview {
                if view! is UITableView {
                    return (view! as UITableView)
                }
            }
            return nil
        }
    }

    var tableViewDataSource:UITableViewDataSource? {
        get {
            return self.tableView?.dataSource
        }
    }

    var tableViewDelegate:UITableViewDelegate? {
        get {
            return self.tableView?.delegate
        }
    }
}
0
David Berry