はじめに
どうも、どうまずです。
Swiftを初めて、最初のほうにやること、『SwiftでTableViewを表示する。』
いくつかのサイトや参考書があり、私もそれらを見ながら作成しました。
しかし、エラーやトラブルで躓いていませんか?
躓きすぎて、匙投げようとしていませんか?
今回は、『swiftでtableViewを表示する』を試みて、よく発生するエラー・トラブルの解決方法を記載しようと思います。
ちなみに、環境は
Swift4
Xcode 9
です。
MainStroryBoardの使い方のトラブル編
ユーティリティエリアが表示されない。(右の作業枠)
XcodeでViewにTableViewを貼り付けようと ユーティリティエリアで説明するように記載されているが、そもそも、ユーティリティエリアってのが表示されていない!
原因
単なる操作ミスで、ユーティリティエリアを隠すボタンをクリックしてしまったようです。
解決策
下記のボタンをクリックして下さい。ユーティリティエリアが表示されます。
Table Viewが二つになった!
MainStoryboardでtable viewをViewControllerを貼り付けたら、View Controllerが二つになってしまった。
説明
「Table View」じゃなくて、「table View Controller」を選択していた。
正:Table View(枠が四角)
誤:Table View Controller(枠が丸、黄色)
解決策
新しくできたViewを削除(選択してDeleteキー)する。 うまく選択できない場合は、左側に「Table View Controller Scene」と表示されているので、選択して削除する。 「Table View Controller」をMainStoryboardに貼り付けただけなら、削除しても問題ありません。
MainStoryBoardとソースの紐付けトラブル編
ソースにTableViewを紐づけたら、テーブル変数名を間違えた
MainStoryboardのTableViewとViewController.swiftなど紐付けしたけど、タイプミスなどでテーブルの変数名を間違えてしまった。
説明
ViewController.swiftに作成された変数名を修正するだけでは、MainStoryboardに設定の名残が残ってしまい、実行してもエラーが発生してしまいます。
MainStoryboardのTableViewとViewController.swiftの紐付けを断つことが大切です。
解決策
- ViewController.swiftのテーブル変数を削除する。
- MainStoryboardのtableViewを2本指でクリックする。
- 下の画面キャプチャの✖︎ボタンをクリックする。
これで、「Table View」とViewController.swiftの紐付けは断たれました。
確認のためシミュレータで実行してみましょう。
エラーが発生しなければ、成功です。
@IBOutlet var mainStoryboard: [UITableView]と表示された。
MainStroryboardのTableViewとViewController.swiftの紐付けを行なった際、
本来、
@IBOutlet weak var mainTableView: UITableView!
と表示されるはずだが、なぜか
@IBOutlet var mainTableView: [UITableView]!
と表示されてしまった。
説明
MainStroryboardのTableViewとViewController.swiftの紐付けを行なったとき、ダイアログが表示されますが、 Connectionのところをデフォルトの「Outlet」ではなく、「Outlet Collection」を選択してしまったようです。
「Outlet Collection」はコレクションつまり配列扱いになります。テーブルを複数使う場合などに活用できますので、完全なミスというわけではありません。
しかし、意図していない場合は・・・単なる操作ミスです。
解決策
やり直しましょう。
「ソースにTableViewを紐づけたら、テーブル変数名を間違えた」を参考にテーブル変数の削除を実施して下さい。
ViewController.swiftの記載編
UITableViewDelegateとUITableViewDataSourceを継承したらエラーになった。
ViewController.swiftでTableViewを操作できるようにUITableViewDataSourceを継承させた。
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
そしたら、
ViewController.swift:11:7: Type 'ViewController' does not conform to protocol 'UITableViewDataSource'
というエラーが発生した。
説明
たぶんですが、デリゲートとデータソースを継承しただけで、作業を止めていませんか?
エラーの内容は
「'ViewController'がプロトコル 'UITableViewDataSource'に準拠していません」
です。
UITableViewDataSourceを継承すると、UITableViewDataSourceのルールに則ったメソッドを用意しなければなりません。
解決策
まず、どこかのサイト、参考書を参照しているのでしたら、このエラーを無視して続きの説明を読みましょう。 大抵の場合は、
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int)
や
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
を記載しているはずです。
特に記載していない場合、エラーのところにFixと出ているはずです。
これをクリックすると、最低限必要なメソッドを自動的に追加してくれます。
補足ですが、
・エラーの左の赤丸の中が白丸の場合は、今回のようにエラー解決案を提示してくれます。
・エラーの左の赤丸の中が!の場合は、エラー解決案を提示してくれませんので、エラー内容から何とか解決しましょう。
TableViewにソースで記載した内容が反映されない。
ある程度なれてきたときに発生するトラブルです。
TableViewの設定や処理をViewController.swiftに記載したのに、シミュレータで実行してみると反映されないというトラブルです。
説明
なにか大切で肝心な何かを忘れています。
解決策
viewDidLoadにデリゲートとデータソースの指定を忘れていませんか?
@IBOutlet weak var mainTableView: UITableView! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. mainTableView.delegate = self mainTableView.dataSource = self }
「mainTableViewのデリゲートとデータソースはこのソース自身に記載しているよ」という指定ですね。 これがないと、mainTableViewはどのデリゲート・データソースを使っていいかわからず、沈黙してしまいます。
全てのセルが同じ設定になってしまう。
例えば、
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return CGFloat(100.0) }
と記述すると、セルの高さが変更されますが、全部のセルが同じ高さになってしまう。
先頭のセルだけ高さを別の高さを指定したい。
説明
heightForRowAtの引数にindexPathがあります。
indexPathには、どのセクションの何行目のセルかという情報が入りますので、これを活用しましょう。
解決策
下記のように条件分岐を記載します。
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { if indexPath.section == 0 && indexPath.row == 0{ return CGFloat(50.0) } return CGFloat(100.0) }
indexPath.sectionでheightForRowAtを呼んだセルのセクション番号を取得します。
indexPath.rowでheightForRowAtを呼んだセルの行番号を取得します。
これらを活用すれば、任意のセルを制御できると思いますよ。
シミュレータで実行しようとしたら編
シミュレータで実行しようとしてエラーになった。
プロジェクト作成直後、とりあえずシミュレータ起動しようとしたら、エラーになっちゃったパターンです。
エラーの内容は下記のような内容。
Signing for "blogTest" requires a development team. Select a development team in the project editor. Code signing is required for product type 'Application' in SDK 'iOS 10.3'
原因
原因はずばり、
何も設定していない実機(○◯のiPhoneなど)を選択している。
です。
Xcodeで作成しているアプリケーションを実機で実行・デバックすることは可能ですが、いろいろと設定が必要です。
その設定をやっていないため、エラーが発生しています。
解決
実機ではなく、シミュレータを選択して、再度実行して下さい。
ここではiPhone7を選択していますが、動かしたい任意のシミュレータを選択して大丈夫です。
AppDelegateクラスに「Thread 1: signal SIGABRT」が発生した。
シミュレータで実行したところ、下のようにAppDelegateクラスに「Thread 1: signal SIGABRT」が発生した。
ログ(デバックエリアの左側の黒いウインドウ)に下記のエラーが出しまった。
BlogTest *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<BlogTest.ViewController 0x7fb824907140> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key mainTableView.'
ちなみに、私は、「Thread 1: signal SIGABR」を「初心者殺し」と呼んでます(笑)
エラーが今まで触ってないところに表示され、何がなんだかキョトンとしてしまいますよね?
私は固まりましたよ!
説明
『そもそも、「signal SIGABR」って何よ?』という方は、 signal SIGABRに関する当ブログの記事をご覧下さい。
この記事の「その1インターフェースビルダーとコードをOutlet引いたのに、そのOutletが外れてしまっているパターン」にハマっています。
テーブルの変数名を間違えたりして、ViewController.swiftのテーブル変数を一度削除したりしてませんか?
テーブルの変数名をViewController.swift上で変更したりしていませんか?
そういう場合に発生します。
解決策
- MainStoryboardのtableViewを2本指でクリックする。
- 下の画面キャプチャの✖︎ボタンをクリックする。
ちゃんと消してから、再度MainStoryboardのTableViewとViewController.swiftを紐付けしましょう。
だいたいこれで、TableViewの器は作れたと思います。
次回は続きのセルの操作時のエラー・トラブルを記載しますので、少々お待ち下さい。