Swiftで複数のカスタムセルを持つUITableview


111

異なるカスタムtableViewCellsでUITableviewを使用したいと思います。私の3つの細胞は次のとおりです。

  • Cell1:画像とラベルが必要です。
  • Cell2:2つのラベルが必要です。
  • Cell3:dayPickerが必要です。

セルのタグをコーディングしたくありません。Swiftでこれをどのように管理できますか?すべてのセルに対して独自のクラスをコーディングする必要がありますか?1つのtableviewControllerを使用できますか?さまざまなセルにデータを入力するにはどうすればよいですか?

iOSデバイスの連絡先アプリのように、tableViewを生成したいと思います。



回答:


270

まず、あなたの質問に答えることから始めましょう。

すべてのセルに独自のクラスをコーディングする必要がありますか?=>はい、そう信じています。少なくとも、私はそのようにします。

1つのtableviewControllerを使用できますか?=>はい、使用できます。ただし、ビューコントローラー内にテーブルビューを配置することもできます。

さまざまなセルにデータを入力するにはどうすればよいですか?=>条件に応じて、さまざまなセルにデータを入力できます。たとえば、最初の2行を最初のタイプのセルのようにしたいとします。したがって、最初のタイプのセルを作成/再利用して、データを設定するだけです。スクリーンショットを表示すると、もっと明確になると思います。

ViewController内のTableViewの例を示します。メインコンセプトを理解したら、とにかく好きなように変更できます。

手順1:3つのカスタムTableViewCellを作成します。FirstCustomTableViewCell、SecondCustomTableViewCell、ThirdCustomTableViewCellという名前を付けました。より意味のある名前を使用する必要があります。

ここに画像の説明を入力してください

ステップ2:Main.storyboardに移動し、TableViewをビューコントローラー内にドラッグアンドドロップします。次に、テーブルビューを選択し、IDインスペクターに移動します。「プロトタイプセル」を3に設定します。ここでは、TableViewに3種類のセルがある可能性があることを伝えました。

ここに画像の説明を入力してください

ステップ3:次に、TableViewとIDインスペクターで最初のセルを選択し、[カスタムクラス]フィールドに「FirstCustomTableViewCell」を入力して、属性インスペクターで識別子を「firstCustomCell」に設定します。

ここに画像の説明を入力してください

ここに画像の説明を入力してください

他のすべてに対して同じことを行います-カスタムクラスをそれぞれ「SecondCustomTableViewCell」および「ThirdCustomTableViewCell」として設定します。また、識別子をsecondCustomCellおよびthirdCustomCellとして連続して設定します。

ステップ4:カスタムセルクラスを編集し、必要に応じてアウトレットを追加します。あなたの質問に基づいて編集しました。

PS:コンセントをクラス定義の下に置く必要があります。

したがって、FirstCustomTableViewCell.swiftでは、

class FirstCustomTableViewCell: UITableViewCell {

ラベルと画像ビューのアウトレットを配置します。

 @IBOutlet weak var myImageView: UIImageView!
 @IBOutlet weak var myLabel: UILabel!

そしてSecondCustomTableViewCell.swiftに、2つのラベルを追加します-

import UIKit

class SecondCustomTableViewCell: UITableViewCell {

    @IBOutlet weak var myLabel_1: UILabel!
    @IBOutlet weak var myLabel_2: UILabel!

    override func awakeFromNib() {
        super.awakeFromNib()
    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }
}

そして、ThirdCustomTableViewCell.swiftは次のようになります。

import UIKit

class ThirdCustomTableViewCell: UITableViewCell {

    @IBOutlet weak var dayPicker: UIDatePicker!

    override func awakeFromNib() {
        super.awakeFromNib()
    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }
}

ステップ5:ViewControllerで、TableViewのアウトレットを作成し、ストーリーボードからの接続を設定します。また、プロトコルリストとして、クラス定義にUITableViewDelegateとUITableViewDataSourceを追加する必要があります。したがって、クラス定義は次のようになります。

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

その後、テーブルビューのUITableViewDelegateとUITableViewDatasourceをコントローラーにアタッチします。この時点で、viewController.swiftは次のようになります。

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

PS:ViewController内でTableViewではなくTableViewControllerを使用する場合は、この手順をスキップできます。

ステップ6:Cellクラスに従って、セルに画像ビューとラベルをドラッグアンドドロップします。ストーリーボードからアウトレットへの接続を提供します。

ステップ7:次に、ビューコントローラーでUITableViewDatasourceに必要なメソッドを記述します。

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 3
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        if indexPath.row == 0 {
            let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "firstCustomCell")
            //set the data here
            return cell
        }
        else if indexPath.row == 1 {
            let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "secondCustomCell")
            //set the data here
            return cell
        }
        else {
            let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "thirdCustomCell")
            //set the data here
            return cell
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

1
func cellForRowAtIndexPathで「タイプ 'UITableViewCell'(0x1dfbfdc)の値を 'Projekt.TitelTableViewCell'(0x89568)にキャストできませんでした」というメッセージが表示されます。UITableViewControllerを使用しており、カスタムセル「TitelZelle」用のクラス「TitelTableViewCell」を持っています。これは、「TitelZelle」セルのIDインスペクターで設定しました。私は何をしなければなりませんか?
Easyglider 2015年

私は私の細胞をキャストしました!TitelTableViewCellを使用して、このセルにカスタムUI要素を入力します。
Easyglider 2015年

7
this => let cell = tableView.dequeueReusableCellWithIdentifier( "TitelZelle"、forIndexPath:indexPath)as TitelTableViewCell
Natasha

2
@PradipKumar、何が問題なの?あなたのエラーは何ですか?ところで、クエリがある場合は質問してください。特定の問題に関してこれを理解または明確にするのに役立つはずのコメントは、著者が投稿した。問題がある場合は、質問して自分の投稿を開始してください。
Natasha

1
numberOfRowsInSectionは、テーブルビューが必要な行数を決定するのに役立ちます。そのため、メソッドは行数を決定するのに役立つ句のみを提供する必要があります。indexpath.row == 0は、すでに行があることを意味しますが、その時点では、テーブルには行があるかどうかがわかりません。だから、あなたはそのようにすべきです。
Natasha

32

Swift 3.0 +最小限のコードで更新

基本概念: 動的セルプロトタイプを使用してテーブルビューを作成します。識別子を割り当て、各セルプロトタイプのカスタムテーブルビューセルクラスを作成します。テーブルビューのデリゲートメソッドでカスタムセルを開始および表示します。

1.ストーリーボードにセルを作成する

tableViewをビューコントローラーにドラッグし、プロトタイプセルを追加してから、UI要素をテーブルビューセルにドロップし、必要に応じて制約を適切に追加します。

ここに画像の説明を入力してください

2.カスタムUITableViewCellクラスを作成する

次のコードをプロジェクトに追加します。ビューコントローラークラスのすぐ上に配置しています。

class FirstTableCell: UITableViewCell {
}

class SecondTableCell: UITableViewCell {
}

class ThirdTableCell: UITableViewCell {   
}

3.カスタムクラスと識別子をセルプロトタイプに割り当てる

ストーリーボードのセルプロトタイプごとに、手順2で作成したカスタムクラスを割り当て、一意の識別子を入力します。

ここに画像の説明を入力してください

4. UI要素をSwiftコードに接続する

コントロールはテーブルビューをドラッグし、ビューコントローラークラスに接続します。手順1でセルプロトタイプに追加されるUI要素をコントロールでドラッグし、対応するテーブルビューのセルクラスに接続します。

ここに画像の説明を入力してください

5.ビューコントローラーとテーブルビューを制御するコードを追加する

ビューコントローラーをテーブルビューデリゲートに準拠させる

class YourViewController: UIViewController, UITableViewDataSource, UITableViewDelegate

viewDidLoad、テーブルビューのデリゲートとデータソースを設定します。

override func viewDidLoad() {
    super.viewDidLoad()

    self.tableView.dataSource = self
    self.tableView.delegate = self

}

最後に、最小要件に従って、テーブルビューを制御する2つのデリゲートメソッドを追加します。

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 3
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if indexPath.row == 0 {
        let cell = tableView.dequeueReusableCell(withIdentifier: "firstTableCell") as! FirstTableCell
        // Set up cell.label
        return cell
    } else if indexPath.row == 1 {
        let cell = tableView.dequeueReusableCell(withIdentifier: "secondTableCell") as! SecondTableCell
        // Set up cell.button
        return cell
    } else {
        let cell = tableView.dequeueReusableCell(withIdentifier: "thirdTableCell") as! ThirdTableCell
        // Set up cell.textField
        return cell
    }
}

6.試してみてください:)

ここに画像の説明を入力してください


素晴らしい!私はあなたのアニメーションが大好きです。
iphaaw 2018年

各セルにヘッダーを付けることは可能ですか?もしそうなら、どのように?
Pruthvi Hariharan

@PruthviHariharanすべてまたはほとんどのセルに「ヘッダー」が必要な場合は、ヘッダーセルまたはセクションヘッダーを実装することはお勧めしません。ヘッダーセルまたはセクションヘッダーを実装することは、管理するためにより多くのコードを必要とし、パフォーマンスに影響します。私の提案は、プロトタイプセルの上にビューを配置し、それを「ヘッダー」のように見せることです
Fangming

@FangmingNing小さな例で説明してください。ありがとう
Pruthvi Hariharan

UIViewControllerの代わりにUITableViewControllerを使用している場合は、手順5は必要ありません。
ディーパックタクル

0

上記の回答が最良の回答ですが、この問題が発生する理由はたくさんあります。この問題を抱えている人のための別の解決策を次に示します。

私の問題は、ストーリーボードビューではなく、ViewControllerクラスに偽装していることでした。ストーリーボードが使用されていなかったので、ストーリーボードセルへの私の参照は無意味でした。

私はこれをしていました:

let viewControllerB = SubViewController()
viewControllerB.passedData = diseases[indexPath.row].name
navigationController?.pushViewController(viewControllerB, animated: true)

そして、私はこのようなことをする必要がありました:

let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "SubViewStoryboardController") as! SubViewController
nextViewController.passedData = diseases[indexPath.row].name
self.present(nextViewController, animated:true, completion:nil)

これが誰かを助けることを願っています。


-22

UITableViewController継承されUIViewController、すでに持っていることUITableviewDataSourceUITableviewDelegate、それ自体にマッピングされました。

サブクラスUITableViewController化するか、TableView内部でを使用できますViewController。その後、でcellForRowAtIndexPath and numberOfRowsInSection宣言されている必要なメソッド()を実装する必要がありますUITableviewDataSource

また、ストーリーボードでは、一意のIDを使用してセルプロトタイプを作成する必要があります。

セルには(タイトル、サブタイトルなどの)基本的なタイプがあります。特別な構成が必要ない場合は、それらも使用できます。

したがって、ピッカーの場合、はい、独自のカスタムセルを作成する必要があります。必要なカスタムUITableViewCellクラス保持日付ピッカーを作成し、デリゲートを使用して目的の結果をに送り返すようにしてくださいViewController

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.