FloatingPanelを使うとStroybardで作ったtableViewがnilになる時

結論、フロートさせるControllerをストーリーボードから生成しよう。

ちょっと練習でTikTokのコメント欄っぽいものを作ろうとして[FloatingPanel](https://github.com/SCENEE/FloatingPanel)を使ったのですが、その際にtableViewがnilになってハマりました。

![スクリーンショット 2020-12-25 21.58.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/1f5754ba-cc33-68ea-a15c-295e5712983f.png)


ちゃんとIBOutletはキチンと紐付けられておりましたが、どうやらViewControllerでcontentViewを生成したときにClassから生成してるもんだから、Storyboardに配置したtableviewが読み込まれてなくてnilになってたようだ。

そこで生成時に`fromStoryboard()`関数を使ってストーリーボードからViewControllerを生成してやるようにすることで無事解決できた。


```ViewController.swift
import UIKit
import FloatingPanel

class ViewController: UIViewController, FloatingPanelControllerDelegate {
    var fpc: FloatingPanelController!

    override func viewDidLoad() {
        super.viewDidLoad()

        fpc = FloatingPanelController()
        fpc.delegate = self // Optional // レイアウトなどを変更しないときは不要

        //let contentVC = CommenttViewController()
        let contentVC = CommentViewController.fromStoryboard()
        fpc.set(contentViewController: contentVC)

        // Track a scroll view(or the siblings) in the content view controller.
        fpc.track(scrollView: contentVC.tableView)

        // Add and show the views managed by the `FloatingPanelController` object to self.view.
        fpc.addPanel(toParent: self)
    }
}
```

```CommentViewController.swift
import UIKit

class CommentViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
		
	@IBOutlet weak var tableView: UITableView!
	@IBOutlet weak var commentCountLabel: UILabel!
	
	override func viewDidLoad() {
		super.viewDidLoad()
		tableView.delegate = self // ここでtableViewがnilになって落ちてた
		tableView.dataSource = self
	}
	
	override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
	
	static func fromStoryboard(_ storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)) -> CommentViewController {
        let controller = storyboard.instantiateViewController(withIdentifier: "CommentViewController") as! CommentViewController
        return controller
    }
	
	func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
		return 10
	}
	
	func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
		let cell = tableView.dequeueReusableCell(withIdentifier: "CommentCell", for: indexPath) as! CommentCell
		return cell
	}
}

```

ストーリーボードからViewControllerを生成するには`Storyboard ID`を設定してやる必要がありますのでこの点だけ注意。

![スクリーンショット 2020-12-25 22.00.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/55cd17ea-7a11-7d2c-918e-25a2193ed300.png)


## おまけ
なお、いつも忘れるのでおさらいですがtableViewの中に直接ProtoTypeCellを入れて作った場合は、以下のようなregisterは必要ないみたいです。ただnibでの登録とClassでの登録の違いを忘れた‥ので優しい人コメントで教えてくれるとうれしい‥。

```swift
tableView.register(UINib(nibName: "CommentCell", bundle: nil), forCellReuseIdentifier: "CommentCell") // storyboardではなく別途xibファイルを作ってCellをデザインしたとき？
tableView.register(CommentCell.self, forCellReuseIdentifier: "CommentCell") //
```

またストーリーボードの Connections Inspector の Outlets で、dataSourceとdelegateを紐付けていれば以下も不要ですが、ぼくはここはコードでやってます。

```swift
tableView.dataSource = self
tableView.delegate = self
```


## 参考
https://ymgsapo.com/2020/08/27/swift-floating-panel/