質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.64%

【Swift】TableViewのCellに、配列のindexPath.rowの値に対応したデータが反映されません

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,871

OGT_kumi

score 13

前提・実現したいこと

swiftで、tableviewを使ったアプリを開発しています。
APIから取得したデータを配列に格納し、
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { }
で、cellごとに配列のindexPath.rowのデータを反映させています(一般的な処理方法かと思います)。
配列の一つに、cellの背景色を指定する文字列を定義しています。
配列の中身は、red、blue、yellowの3色が定義されており、その値に応じてcellの背景色が変わるよう処理を記載しています。

発生している問題・エラーメッセージ

配列の中身に対応した色がcellの背景色に設定されず、関係ない色がセットされてしまいます。
下に該当する箇所のコードを記載しています。
配列に正しい順序でデータが格納されていることは、print()を使って確認しています。
背景色に正しく反映されていないという状況です。

なんとなく、tableviewの描写タイミングのルールを理解しきれていないのかな、、、という所感はあり色々調べてみたものの、これという解決方法が見つかっていません。

不足情報などあればご指摘ください。

該当のソースコード

viewcontoller側

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell") as! PeopleListCell
    cell.selectionStyle = UITableViewCell.SelectionStyle.none

    cell.BGcolor=self.peopleColor[indexPath.row] // 背景色データをcellに設定
    cell.backgroundColorSet() // cellに定義したfuncを使用し、背景色データ毎に背景色を指定
    print(self.peopleColor[indexPath.row]) // 配列に格納されているデータを確認
    return cell
  }


cell側で背景色を設定するメソッド

  func backgroundColorSet(){
    // background Redの設定
    let colorRed1 = UIColor(red: 255/256.0, green: 82/256.0, blue: 119/256.0, alpha: 1).cgColor   // 左上
    let colorRed2 = UIColor(red: 253/256.0, green: 10/256.0, blue: 61/256.0, alpha: 1).cgColor    // 右下
    gradientLayerRed.colors = [colorRed1, colorRed2]
    gradientLayerRed.startPoint = CGPoint.init(x: 0, y: 0)
    gradientLayerRed.endPoint = CGPoint.init(x: 1 , y:1)

    // background Yellowの設定
    let colorYellow1 = UIColor(red: 249/256.0, green: 193/256.0, blue: 0/256.0, alpha: 1).cgColor   // 左上
    let colorYellow2 = UIColor(red: 245/256.0, green: 127/256.0, blue: 0/256.0, alpha: 1).cgColor    // 右下
    gradientLayerYellow.colors = [colorYellow1, colorYellow2]
    gradientLayerYellow.startPoint = CGPoint.init(x: 0, y: 0)
    gradientLayerYellow.endPoint = CGPoint.init(x: 1 , y:1)

    //background Greenの設定
    let colorGreen1 = UIColor(red: 73/256.0, green: 253/256.0, blue: 223/256.0, alpha: 1).cgColor   // 左上
    let colorGreen2 = UIColor(red: 0/256.0, green: 170/256.0, blue: 147/256.0, alpha: 1).cgColor    // 右下
    gradientLayerGreen.colors = [colorGreen1, colorGreen2]
    gradientLayerGreen.startPoint = CGPoint.init(x: 0, y: 0)
    gradientLayerGreen.endPoint = CGPoint.init(x: 1 , y:1)

    if BGcolor=="red"{
      gradientLayerRed.frame = tagView.bounds
      tagView.layer.insertSublayer(gradientLayerRed, at:0)
    } else if BGcolor=="yellow"{
      gradientLayerYellow.frame = tagView.bounds
      tagView.layer.insertSublayer(gradientLayerYellow, at:0)
    } else {
      gradientLayerGreen.frame = tagView.bounds
      tagView.layer.insertSublayer(gradientLayerGreen, at:0)
    }
  }

print(self.peopleColor[indexPath.row])の中身

初期画面での出力内容を①
そこから少しスクロールした状態での出力内容を②
最後までスクロールした状態での出力内容を③
として記載しています。

red
red
red
red
red    →少しスクロールすると、ここから先が繰り返される
blue
blue
red
blue
red
red
yellow
blue
yellow
———————↑①ここまでが、初期画面状態でのprint
red
blue
blue
red
blue
red
red
yellow
blue
yellow
———————↑②少しスクロールすると、ここまで表示される
yellow
blue
yellow
red
red
yellow
red
red
red
blue
blue
blue
blue
blue
———————↑③最後までスクロールすると、ここまで表示される(規則性不明)

PeopleListCell.swiftの中身

import UIKit

class PeopleListCell: UITableViewCell {

  @IBOutlet weak var tagView: CustomView!
  @IBOutlet weak var ownerImage: UIImageView!
  @IBOutlet weak var peopleName: UILabel!
  @IBOutlet weak var memberCount: UILabel!
  var BGcolor: String?
  var gradientLayerRed = CAGradientLayer()
  var gradientLayerYellow = CAGradientLayer()
  var gradientLayerGreen = CAGradientLayer()

    override func awakeFromNib() {
        super.awakeFromNib()

      tagView.roundCorners(corners: [.topRight, .bottomRight], radius: 15)

      self.layer.shadowColor = UIColor.black.cgColor
      self.layer.shadowOpacity = 0.5 // 透明度
      self.layer.shadowOffset = CGSize(width: 3, height: 3) // 距離
      self.layer.shadowRadius = 3 // ぼかし量

    //  backgroundColorSet()


    }

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

  func backgroundColorSet(){
    // background Redの設定
    let colorRed1 = UIColor(red: 255/256.0, green: 82/256.0, blue: 119/256.0, alpha: 1).cgColor   // 左上
    let colorRed2 = UIColor(red: 253/256.0, green: 10/256.0, blue: 61/256.0, alpha: 1).cgColor    // 右下
    gradientLayerRed.colors = [colorRed1, colorRed2]
    gradientLayerRed.startPoint = CGPoint.init(x: 0, y: 0)
    gradientLayerRed.endPoint = CGPoint.init(x: 1 , y:1)

    // background Yellowの設定
    let colorYellow1 = UIColor(red: 249/256.0, green: 193/256.0, blue: 0/256.0, alpha: 1).cgColor   // 左上
    let colorYellow2 = UIColor(red: 245/256.0, green: 127/256.0, blue: 0/256.0, alpha: 1).cgColor    // 右下
    gradientLayerYellow.colors = [colorYellow1, colorYellow2]
    gradientLayerYellow.startPoint = CGPoint.init(x: 0, y: 0)
    gradientLayerYellow.endPoint = CGPoint.init(x: 1 , y:1)

    //background Greenの設定
    let colorGreen1 = UIColor(red: 73/256.0, green: 253/256.0, blue: 223/256.0, alpha: 1).cgColor   // 左上
    let colorGreen2 = UIColor(red: 0/256.0, green: 170/256.0, blue: 147/256.0, alpha: 1).cgColor    // 右下
    gradientLayerGreen.colors = [colorGreen1, colorGreen2]
    gradientLayerGreen.startPoint = CGPoint.init(x: 0, y: 0)
    gradientLayerGreen.endPoint = CGPoint.init(x: 1 , y:1)

    if BGcolor=="red"{
      gradientLayerRed.frame = tagView.bounds
      tagView.layer.insertSublayer(gradientLayerRed, at:0)
    } else if BGcolor=="yellow"{
      gradientLayerYellow.frame = tagView.bounds
      tagView.layer.insertSublayer(gradientLayerYellow, at:0)
    } else {
      gradientLayerGreen.frame = tagView.bounds
      tagView.layer.insertSublayer(gradientLayerGreen, at:0)
    }
  }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • hameji001

    2019/01/13 00:05

    peopleColorの配列の中身のprintとPeopleListCellのファイルのコード
    を載せていただけないでしょうか?

    キャンセル

  • OGT_kumi

    2019/01/14 22:03

    ご連絡遅れてしまい申し訳ありません。上記2点、追記したのでご確認ください。

    キャンセル

回答 1

checkベストアンサー

0

回答遅くなりました。試してみました。
元データの形がわからなかったので、「仮形式」で答えさせていただきます。

うまくしっくりと説明できませんが、  

func backgroundColorSet(){ }


自体にindexPathとの繋がりがないので、
cellがreuseされる際に、以前のセットの値BGcolorが残ってるものが存在し、
そのために色がめちゃくちゃになってしまっていると思います。

以下のようにbackgroundColorとindexPathを一対にして表示する必要があります。

// TableViewController.swift
// 仮データ形式
self.data = ["yellow", "red", "yellow",
             "green", "red", "yellow",
             "green", "red", "yellow",
             "green", "red", "yellow",
             "green", "red", "yellow",
             "green", "red", "yellow",
             "green", "red", "yellow",
             "green", "red", "yellow",
             "green", "red", "yellow",
             "green", "red", "yellow",
             "green", "red", "yellow",
             "green", "red", "yellow", "green"]


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "customCell") as! CustomCell
    cell.selectionStyle = UITableViewCell.SelectionStyle.none

    cell.setCell(indexPath: indexPath, data: self.data)
    cell.peopleName.text = String(indexPath.row) // 確認用
    print("\(indexPath.row), = \(self.data[indexPath.row])") // これで、配列の番号と表示色の確認を
    return cell
}

// CustomCell.swift
@IBOutlet weak var tagView: CustomView!
@IBOutlet weak var ownerImage: UIImageView!
@IBOutlet weak var peopleName: UILabel!
@IBOutlet weak var memberCount: UILabel!
var gradientLayer = CAGradientLayer()

func setCell(indexPath: IndexPath, data: [String]) {
    self.gradientLayer.frame = tagView.bounds
    gradientLayer.startPoint = CGPoint.init(x: 0, y: 0)
    gradientLayer.endPoint = CGPoint.init(x: 1 , y:1)
    let color = data[indexPath.row]
    switch color {
        case "red":
            let colorRed1 = UIColor(red: 255/256.0, green: 82/256.0, blue: 119/256.0, alpha: 1).cgColor   // 左上
            let colorRed2 = UIColor(red: 253/256.0, green: 10/256.0, blue: 61/256.0, alpha: 1).cgColor    // 右下
            gradientLayer.colors = [colorRed1, colorRed2]
        case "yellow":
            let colorYellow1 = UIColor(red: 249/256.0, green: 193/256.0, blue: 0/256.0, alpha: 1).cgColor   // 左上
            let colorYellow2 = UIColor(red: 245/256.0, green: 127/256.0, blue: 0/256.0, alpha: 1).cgColor    // 右
            gradientLayer.colors = [colorYellow1, colorYellow2]
        default:
            let colorGreen1 = UIColor(red: 73/256.0, green: 253/256.0, blue: 223/256.0, alpha: 1).cgColor   // 左上
            let colorGreen2 = UIColor(red: 0/256.0, green: 170/256.0, blue: 147/256.0, alpha: 1).cgColor    // 右下
            gradientLayer.colors = [colorGreen1, colorGreen2]
    }
    tagView.layer.insertSublayer(gradientLayer, at:0)
    // ちなみに、他のデータもここでセットすべきです。データの形に合わせて取り出してくださいね。
    ownerImage.image = UIImage(named: /* self.data.name[indexPath.row] */)
    peopleName.text = /* self.data.....等 */
}

これでずれないはずです。
自分もこのsetCellの方法どこかのサイトからのコピーですけどね。
OGT_kumiさんようにカスタムしました。
赤のみを表示する時に緑や黄色を読み込む必要ないですよね。
メモリの節約でswitch以下に移動しました。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/19 13:20

    すごい!見事直りました!こんな丁寧に書いてくださりありがとうございます!!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.64%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る