2017-07-17 27 views
1

後に消え、私のカスタムセルクラスである:以下いくつかのテーブルビューのセルの内容をスクロール(SWIFT)以下

class AthleteTableViewCell: UITableViewCell { 

var myLabel1: UILabel! 
var myLabel2: UILabel! 
var profile: UIImageView! 
var star = StarButton() 
var touched = false 

required init(coder aDecoder: NSCoder) { 
    fatalError("init(coder:)") 
} 

override init(style: UITableViewCellStyle, reuseIdentifier: String?) { 
    super.init(style: style, reuseIdentifier: reuseIdentifier) 

    let gap : CGFloat = 10 
    let labelHeight: CGFloat = 30 
    let labelWidth: CGFloat = 150 
    let lineGap : CGFloat = 5 
    let label2Y : CGFloat = gap + labelHeight + lineGap 


    myLabel1 = UILabel() 
    myLabel1.frame = CGRect(x: gap, y: gap, width: labelWidth, height: labelHeight) 
    myLabel1.textColor = UIColor.black 
    contentView.addSubview(myLabel1) 

    myLabel2 = UILabel() 
    myLabel2.frame = CGRect(x: gap * 5, y: label2Y, width: labelHeight, height: labelHeight) 
    myLabel2.textColor = UIColor.white 
    myLabel2.textAlignment = .center 
    myLabel2.backgroundColor = UIColor.flatMint() 
    myLabel2.layer.cornerRadius = 15.0 
    myLabel2.clipsToBounds = true 
    contentView.addSubview(myLabel2) 

    profile = UIImageView() 
    profile.image = UIImage() 
    profile.frame = CGRect(x: bounds.width - gap, y: bounds.height/2, width: bounds.height * 1.25, height: bounds.height * 1.25) 
    profile.layer.cornerRadius = (bounds.height * 1.25)/2 
    profile.layer.masksToBounds = true 
    contentView.addSubview(profile) 

    if (touched != false) { 
     star.isSelected = true 
     star.frame = CGRect(x: gap, y: label2Y, width: labelHeight, height: labelHeight) 
     contentView.addSubview(star) 
    } else { 
     star.frame = CGRect(x: gap, y: label2Y, width: labelHeight, height: labelHeight) 
     contentView.addSubview(star) 
     star.isEnabled = true 
    } 
} 

}

とは、私の細胞を作成するための方法である:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    let cell = AthleteTableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "myCell") 

    cell.myLabel1.text = "\(myArray[indexPath.row])" 
    cell.myLabel1.textColor = UIColor.white 
    cell.myLabel2.isHidden = true 

    cell.profile.image = UIImage(named: cell.myLabel1.text!) 

    cellArray.append(cell) 

    if (cell.touched) { 
     cell.star.isSelected = true 
    } else { 
     cell.star.isOpaque = true 
    } 

    cell.backgroundColor = UIColor(white: 1, alpha: 0.2) 

    return cell 
} 

と以下は、最終的な状態をテーブルビューのセルに残しておきたいアニメーションをトリップするセルを選択する方法です。

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 
    makeSelection(tableView, didSelectRowAt: indexPath) 
} 

func makeSelection(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 
    let cell = tableView.cellForRow(at: indexPath) as! AthleteTableViewCell 
    cell.selectionStyle = UITableViewCellSelectionStyle.none 

    if(selectionArray.contains(myArray.object(at: indexPath.row))) { 
     //Popping selection off of the stack and updating all labels 
     updateLabels(tableView: tableView) 
     selectionArray.remove(myArray[indexPath.row]) 
     cell.star.isFavorite = false 
     cell.myLabel2?.isHidden = true 
     //need to somehow implement all of the rank labels decreasing by one if I deselect someone 
     cell.touched = false 
     //updateLabels(tableView: tableView) 
    } else { 
     selectionArray.add(myArray[indexPath.row]) 
     cell.touched = true 
     let rank = selectionArray.count 
     cell.myLabel2.isHidden = false 
     cell.myLabel2?.text = "\(rank)" 
     cell.star.isFavorite = true 
    } 
} 

これは、あなたがそれを選択すると、細胞がどのように見えるかの写真です:

enter image description here

と、これはスクロールダウンした後に、その同じセルの写真であるので、それは視野の外にあるとその後、バックスクロール:

enter image description here

何かが明確にここに非常にうまくいかない - 私は「触れていることを追加しました"セルが再描画されている可能性があるという仮定の下でカスタム表ビューのセルクラスにブーリアンをかけ、その星をアニメーション化する必要があるかどうかを知る方法がなかったため、仕事(多分私は何かに乗っていますが、それは間違って実装されていますか?)

ここで何が起こっているのか分かりませんか?本当にありがとう!!!

+0

これは古典的なセルリサイクルのバグのようです。 'UITableView'は、オフスクリーンのときにセルを保持せず、再利用のためにリサイクルします。実際のモデルデータがセルに格納されることはできません。 – marko

+0

触った部分をセルではなくデータストアに保存するのが理想です。あなたのセルは情報の格納には使用されません。だからあなたのセルがクリックされるたびに、その特定の項目のデータストアを更新する必要がありますtouched == trueとし、テーブルビューを再読み込みします。 –

+0

@kapsymあなたが「その特定のアイテムのデータストアを更新する」と言ったら、どういう意味ですか? –

答えて

2

コードにはさまざまな問題があります。 tableView(_:cellForRowAt:)メソッドでは、dequeueReusableCell(withIdentifier:for:)を呼び出す必要があります。

コンテンツを読み込むためにセルからデータを読み取ろうとしてはいけません。状態データをある種のデータモデルに保存する必要があります。配列は、単一のセクションを持つテーブルビューでうまく機能し、配列の配列はセクション化されたテーブルビューでうまく機能します。

テーブルビューを使用する方法については、無数のチュートリアルがあります。読書をする必要があります。

+0

私のtableviewには1つのセクションしかありません。したがってアレイ。 –

+0

しかし、 'cellForRow(at:)'メソッドは、選択したセルの配列をチェックして、セルを選択したものとして設定するかどうかを確認しません。それは 'dequeueReusableCell(withIdentifier:for:)'を呼び出さないことに加えてです。 –

0

データ

struct Profile { 
var personName: String? 
var photoURL: String? 
var rank: String? 
var isTouched: Bool? 

// add init method and stuff 
} 

2)これらのプロファイル要素を使用して、配列を移入するためにステップのプロセス

1)構造体を作成することによりステップとして、ここでの答えとしてそれを言及。最終的にあなたは一連のプロファイルを持っています。

3)この配列を使用して、Profileオブジェクトからデータを取得する各セル要素でtableviewを作成します。あなたのcellForRowAt方法の使用dequeueReusableCell(withIdentifierで

4):については:)その特定のプロファイルのために、isTouchedが真であるならば、他の

cell.star.isFavorite = true 

を示し、あなたの細胞を初期化し、値

5)を割り当てます偽に設定してください

6)あなたのdidSelectRowで、indexpathを取得してください。あなたのプロファイルの配列でProfile.isTouched = true/falseを設定し、その特定の行のニーズに応じてそれに応じて切り替えます。プロファイル配列を新しいプロファイルオブジェクトで更新します。

7)refresh tableview。

関連する問題