简体   繁体   中英

swift: UITableViewCell data overlapped when scrolling down and up

Im new to Swift , and writing an app that using Table View . I am building the cell in cellForRowAtIndexPath , but when I scroll down and up again the data of the previous cell is not cleaned, and I see overlapped data on the fields. this is my code

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    cellArrayIndex = cellsPointerArray[indexPath.row] as! Int

    let cell = self.tableView.dequeueReusableCellWithIdentifier("gameCell",forIndexPath: indexPath) as UITableViewCell

    var indexInGamesArray = 0
    let btnWidth = CGFloat((cell.frame.width / 100) * 20)
    let teamSignWidth = CGFloat((cell.frame.width / 100) * 4)
    let gapWidth = CGFloat((cell.frame.width / 100) * 3)

    //***** fixet fields iv every cell
    let lblTop = UILabel(frame: CGRectMake(0 ,0,self.frame.size.width, 25))
    lblTop.backgroundColor = UIColor(red: 88/255, green: 88/255, blue: 88/255, alpha: 1)
    cell.addSubview(lblTop)

    let lblDate = UILabel(frame: CGRectMake(lblTop.frame.origin.x + 30.0,lblTop.frame.origin.y,100,lblTop.frame.size.height))
    lblDate.backgroundColor = UIColor.clearColor()

    let lblTime = UILabel(frame: CGRectMake(lblDate.frame.origin.x + lblDate.frame.size.width + 30.0,lblTop.frame.origin.y,300,lblTop.frame.size.height))
    lblTime.backgroundColor = UIColor.clearColor()

    let str : String = (gamesArray[cellArrayIndex]["GameDate"] as? String)!
    let characterToFind: Character = "T"
    let indexForCharacterInString = str.characters.indexOf(characterToFind)
    let dateStr:String = str.substringToIndex(indexForCharacterInString!)
    lblDate.text = dateStr
    lblDate.textColor = UIColor.yellowColor()
    cell.addSubview(lblDate)

    var timeStr:String = str.substringFromIndex(indexForCharacterInString!)
    timeStr.removeAtIndex(str.characters.indices.first!)
    lblTime.text = timeStr
    lblTime.textColor = UIColor.yellowColor()
    cell.addSubview(lblTime)

    let lblHomName = UILabel(frame: CGRectMake(20,lblDate.frame.origin.y + lblDate.frame.size.height,self.frame.size.width/2 - 30,25))
    lblHomName.font = const.smallFont
    lblHomName.text = gamesArray[cellArrayIndex]["HomeName"] as? String


    let HcapLine = gamesArray[cellArrayIndex]["HcapLine"] as? Int
    if(HcapLine < 0){
        lblHomName.textColor = UIColor.redColor()
    }
    else{
        lblHomName.textColor = const.lblColorSTD
    }
    cell.addSubview(lblHomName)

    let lblAwayName = UILabel(frame: CGRectMake(self.frame.width/2 + 20,lblDate.frame.origin.y + lblDate.frame.size.height,self.frame.size.width/2 - 30,25))
    lblAwayName.font = const.smallFont
    lblAwayName.text = gamesArray[cellArrayIndex]["AwayName"] as? String

    if(HcapLine < 0){
        lblAwayName.textColor = UIColor.redColor()
    }
    else{
        lblAwayName.textColor = const.lblColorSTD
    }
    cell.addSubview(lblAwayName)

    let lblHC = UILabel(frame: CGRectMake(cell.frame.width/2 - 80,lblAwayName.frame.origin.y + lblAwayName.frame.size.height,self.frame.size.width/2 - 30,25))
    lblHC.text = "Handicap"
    lblHC.textColor = UIColor.redColor()
    lblHC.font = const.smallBoldFont
    cell.addSubview(lblHC)

    let lblTL = UILabel(frame: CGRectMake(cell.frame.width/2 + 40,lblAwayName.frame.origin.y + lblAwayName.frame.size.height,self.frame.size.width/2 - 30,25))
    lblTL.text = "Total Line"
    lblTL.textColor = UIColor.redColor()
    lblTL.font = const.smallBoldFont
    cell.addSubview(lblTL)

    //***** end if fixed fields block

    //***************************************
    //***** Build the lines of the cell *****
    //***************************************
print("gamesArray.count: ",gamesArray.count)
    let NumberOfLines = numOfGamesArray[indexPath.row] as! Int

    indexInGamesArray = (cellsPointerArray[indexPath.row] as! Int) //- 1
    print("indexPath.row:",indexPath.row)
    print("NumberOfLines:" ,NumberOfLines)


    for(var i = 0;i <= NumberOfLines; i++){

        let lineMultiplayer = CGFloat(i)

        let gameView = UIView(frame: CGRectMake(0,CGFloat(i * 60) + lblTL.frame.origin.y + lblTL.frame.height ,cell.frame.width,60))

        let lblH = UILabel(frame: CGRectMake(0,lineMultiplayer * 25,teamSignWidth,25))
        print ("blH.frame.origin.y: ",lblH.frame.origin.y)
        lblH.text = " H"
        lblH.textColor = const.lblColorSTD
        lblH.font = const.smallFont
        gameView.addSubview(lblH)

        let lblHcapLine = UILabel(frame: CGRectMake(lblH.frame.origin.x + lblH.frame.width, lblH.frame.origin.y,btnWidth,25))
        lblHcapLine.layer.borderColor = const.lblColorSTD.CGColor
        lblHcapLine.layer.borderWidth = 1
        lblHcapLine.textColor = const.lblColorSTD
        lblHcapLine.font = const.stdLblFont
        print("gamesArray[indexInGamesArray][\"HcapLine\"]:" ,gamesArray[indexInGamesArray]["HcapLine"])
        print("indexInGamesArray: ",indexInGamesArray)
        lblHcapLine.text = (gamesArray[indexInGamesArray]["HcapLine"])!!.description
        lblHcapLine.textAlignment = NSTextAlignment.Center
        gameView.addSubview(lblHcapLine)

        cell.addSubview(gameView)
         indexInGamesArray++

    }
    cellArrayIndex = 0

    //***** Build the lines of the cell block end

    return cell
}

You are adding labels as subview in UITableViewCell But when cell is reused this again adds the labels as subview in cell but the label you added before is still there so you need to remove label from uitableview cell before adding this as subview. for eg

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    cellArrayIndex = cellsPointerArray[indexPath.row] as! Int

    let cell = self.tableView.dequeueReusableCellWithIdentifier("gameCell",forIndexPath: indexPath) as UITableViewCell

    var indexInGamesArray = 0
    let btnWidth = CGFloat((cell.frame.width / 100) * 20)
    let teamSignWidth = CGFloat((cell.frame.width / 100) * 4)
    let gapWidth = CGFloat((cell.frame.width / 100) * 3)

    //***** fixet fields iv every cell
    let lblTop = UILabel(frame: CGRectMake(0 ,0,self.frame.size.width, 25))
    lblTop.backgroundColor = UIColor(red: 88/255, green: 88/255, blue: 88/255, alpha: 1)

   for let view in cell.subviews
   {
      if view isKindOfClass: [UILabel Class]
      {
          [view removeFromSuperview];
        }

    }

    cell.addSubview(lblTop)


   return cell;
}

What dequeueReusableCellWithIdentifier does is recycling the old cell to use again if it was already created to. So what your code did is adding subviews to the cells and then when you scroll it recycle the old cells and add more subviews to it again and again so it overlapped.

What you should do is to design all the subviews in Storyboard and in cellForRowAtIndexPath you only set the data http://www.raywenderlich.com/50308/storyboards-tutorial-in-ios-7-part-1

Dequeued cells are not nil . Therefore, when the cell is reused you are adding more UILabel 's on top of the UILabel s that already exist.

首先,谢谢大家,所有答案都在其中包含了解决方案,我结束了从该单元格中删除所有子视图的操作,因为它是一个动态单元格,可以在其中容纳不同数量的字段,而且我不知道它们又有多少个不适谢谢你们!

This is the most frustrating issue i faced during my early iOS Swift development. I tried nearly everything but nothing seemed to work perfectly. Then after more than a week of research i found this heavenly swift open source library called kingfisher on github that fixed this issue. It also uses asynchronous image cache that will make your app a lot faster
Github link

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM