2017-11-30 5 views
1

でもuglyのコードを修正しようとしています。スイフト:変数テーブルとしてキャストテーブルセル

私のアプリには5つのTableViewがあり、それぞれ異なるタイプのデータを表示します(セルのレイアウトが異なる)。データ型は似ていて類似したメソッド(ダウンロード、エンコーディングなど)が必要なため、私はTableViewController:UITableViewControllerクラスを設定して、5つのTableViewControllerサブクラスのスーパークラスとして機能します。このスーパークラスの中で、私は標準の "cellForRowAt"メソッドを持っていますが、膨大かつ繰り返しています。私はそれを簡素化したい。

私の問題(私は思う)は複数の "let cell ="ステートメントで、データ型に応じて異なるタイプのTableViewCellとしてキャストされます。たとえば、私のDataType.SCHEDULESデータ型は、 "SchedulesCell"というreuseIDを持つSchedulesTableViewCellを取得する必要があります。彼らはそれぞれ独自のIBOutletビューを持っているので、私はそれらをすべて同じTableViewCellクラスにすることはできません。

醜いことに、各tableViewには2つのセルプロトタイプがあり、各データ型に対してARTICLEセルとDETAILセルを生成できる必要があります。

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

    // get the article and row type 
    let article = getArticleFor(indexPath: indexPath) 
    let cellType = getCellTypeFor(indexPath: indexPath) 

    // create either an ARTICLE row or a DETAIL row. 
    // (simplified for SO posting. Each "case" is actually 
    // 5-6 lines of nearly identical code) 
    switch cellType { 

    // for the ARTICLE cell prototype 
    case CellType.ARTICLE: 

     // get the right table cell matching the datatype 
     switch self.datatype { 

     case DataType.SCHEDULES: 
      let cell = tableView.dequeueReusableCell(withIdentifier: "SchedulesCell") as! SchedulesTableViewCell 
      cell.fillCellWith(article: article) 
      cell.otherMethod2() 
      cell.otherMethod3() 
      return cell 

     case DataType.LUNCH: 
      let cell = tableView.dequeueReusableCell(withIdentifier: "LunchCell") as! LunchTableViewCell 
      cell.fillCellWith(article: article) 
      cell.otherMethod2() 
      cell.otherMethod3() 
      return cell 

     case DataType.EVENTS: 
      let cell = tableView.dequeueReusableCell(withIdentifier: "EventsCell") as! EventsTableViewCell 
      cell.fillCellWith(article: article) 
      cell.otherMethod2() 
      cell.otherMethod3() 
      return cell 

     case DataType.DAILY_ANN: 
      let cell = tableView.dequeueReusableCell(withIdentifier: "DailyannCell") as! DailyannTableViewCell 
      cell.fillCellWith(article: article) 
      cell.otherMethod2() 
      cell.otherMethod3() 
      return cell 

     case DataType.NEWS: 
      let cell = tableView.dequeueReusableCell(withIdentifier: "NewsCell") as! NewsTableViewCell 
      cell.fillCellWith(article: article) 
      cell.otherMethod2() 
      cell.otherMethod3() 
      return cell 

     } 
    // or for the DETAIL cell prototype 
    case CellType.DETAIL: 

     // get the right table cell matching the datatype 
     switch self.datatype { 

     case DataType.SCHEDULES: 
      let cell = tableView.dequeueReusableCell(withIdentifier: "SchedulesDetailsCell") as! ScheduleDetailTableViewCell 
      cell.fillCellWith(article: article) 
      cell.otherMethod2() 
      cell.otherMethod3() 
      return cell 

     case DataType.LUNCH: 
      let cell = tableView.dequeueReusableCell(withIdentifier: "LunchDetailsCell") as! LunchDetailsTableViewCell 
      cell.fillCellWith(article: article) 
      cell.otherMethod2() 
      cell.otherMethod3() 
      return cell 

     case DataType.EVENTS: 
      let cell = tableView.dequeueReusableCell(withIdentifier: "EventsDetailsCell") as! EventsDetailTableViewCell 
      cell.fillCellWith(article: article) 
      cell.otherMethod2() 
      cell.otherMethod3() 
      return cell 

     case DataType.DAILY_ANN: 
      let cell = tableView.dequeueReusableCell(withIdentifier: "DailyannDetailCell") as! DailyannDetailsTableViewCell 
      cell.fillCellWith(article: article) 
      cell.otherMethod2() 
      cell.otherMethod3() 
      return cell 

     case DataType.NEWS: 
      let cell = tableView.dequeueReusableCell(withIdentifier: "NewsDetailCell") as! NewsDetailTableViewCell 
      cell.fillCellWith(article: article) 
      cell.otherMethod2() 
      cell.otherMethod3() 
      return cell 
     } 
    } 
} 

私はもともとサブクラス自身の 『cellForRowAt』メソッド内の各「聞かせてセル=」ケースがあったが、私は愚かに思えたすべてのサブクラスに非常によく似たコードを繰り返しました。一方、上のコードは反復を単一のクラスに移動しましたが、反復を削除しなかったので、それはまだ愚かですが、別の場所です。

私は、このような何かをするクラスの辞書を作ることができれば、私はその後、私のような、より一般的な私の「聞かせてセル=」文を作ることができる...

let tableCellClasses = [DataType.SCHEDULES : ScheduleTableViewCell, 
        DataType.LUNCH : LunchTableViewCell 
        etc. 

...のように感じます...

let cell = tableView.dequeueReusableCell(withIdentifier: identifier[dataType]) as! tableCellClasses[dataType] 

しかし、それを動作させる方法を見つけることができないようです。

私が言ったように、それは動作しますが、それは醜いです。私は高校で働いているので、クリーンで構造の整ったコードを見るためにレポを見ている学生に欲しいです。

提案がありますか?

答えて

1

あなたはスウィフトのメタタイプを使用してものではありませんが、あなたのコードを見て、すべてのセルのサブクラスは、同じ方法で共有することができます:

  • 基本クラスを持っている:いないのはなぜ

    cell.fillCellWith(article: article) 
    cell.otherMethod2() 
    cell.otherMethod3() 
    

    を上記のインタフェース(セルをデキューした後に使用する3つのメソッドで、それぞれの具象サブクラスでオーバーライドされる可能性がある3つのメソッド)を実装するすべてのカスタムセルクラスを継承します。メソッドwの正しい実装を信じて各サブクラスごとに実行される。キャストはコンパイラを幸せにするだけです:UITableViewCellにはこれらのメソッドがありません)。

  • はあなたに

  • がstoryobard上の特定のクラスに設定し、各プロトタイプのセルを持っている特定のセル識別子を与え、データ型のスイッチ句を持って、そしてあまりにも固有の識別子を割り当てます。

意味がありますか?

今、あなたのコードを見て、あなたは本当に異なっているように見えませんサブクラス同じUITableViewCellサブクラスのいくつかの異なるプロトタイプを持つことは、まったく問題ありません。サブビューレイアウトとサブセット別のカスタムプロパティ/メソッドが同じであれば、それぞれ異なるサブビューレイアウトと異なる再利用識別子があります。

+0

TableViewCell基本クラスを作成すると、サブクラスのIBOutletビューにアクセスできなくなります。したがって、私が "let cell ="ステートメントを呼び出すとき、それらが基本クラスとしてキャストされていれば、基本クラス・メソッドはサブクラス・セル・ビューに移入できません。 私は誤解していますか? –

+0

私は、identifiy inpsectorの各プロトタイプセルに適切なサブクラスを設定すると、ストーリーボードは要求されたとおりにインスタンス化すると思います。基本クラスへのキャストは基本クラスのインスタンスに変換されませんが、それはコンパイルエラーを起こさずに 'fillCellWith(article:)'を呼び出すことができます。特定のサブクラスがメソッドをオーバーライドする場合は、オーバーライドされた実装が呼び出されます。コンセント設定はセルのサブクラスのソースコードで実行する必要があります。したがって、テーブルビューコントローラから分離された実装の詳細です。 –

+0

おそらく、 'dequeueReusableCell(withIdentifier :, for:)'を使用してください。 –

-1

あなたが想定していることを行う方法はありません。必要に応じてクラスを1つずつキャストしなければなりません。または、必要なすべてのメソッドを実装し、それらをデータ型で呼び出す基本クラスを使用できます。

関連する問題