在swift中向tableViewCell动态添加多个视图时,UIViews重叠

时间:2016-06-15 13:13:10

标签: ios swift uitableview

我想在表格单元格中添加一些n视图(假设每个视图都是一行)。基于designerExpertiseList计数,我为每一行创建了一个视图,并添加了1个图像视图和1个标签。

但是当我滚动时,单元格的数据不正确。如果我长按一个单元格,我可以看到一个不同的视图与现在可见的视图重叠。请查看附带的屏幕截图

第一次加载视图时:http://i.stack.imgur.com/M8itL.png
向下滚动后,再次向上滚动并长按:http://i.stack.imgur.com/AuTG0.png

当我向上滚动时,对于少数单元格来说第一次正确的数据,即使是搞砸了。我甚至试图在First Render上添加这些dynamic views一次。

有全球声明:

let rowHeight:CGFloat = 20.0
let imageWidth:CGFloat = 15.0
let imageHeight:CGFloat = 15.0
let labelX:CGFloat = 30.0
let labelHeight:CGFloat = 20.0
var firstRender:[Bool] = [Bool]()


tableView cellForRowAtIndexPath方法中的代码:

self.designer = AppController.getElementFromDesignersList(indexPath.section)

        cell.designerName.text = designer.getFirstName() + " " + designer.getLastName()
        cell.location.text = designer.getAddress()

        // Add more ROWS of expertise if exist! Getting only 1st expertise now, if it exists
        let expertiseList = self.designer.getExpertiseList()

        if self.firstRender[indexPath.section] {
            var i:Int = 0
            for e in expertiseList {
                let v = UIView(frame: CGRectMake(0, CGFloat(i)*rowHeight, cell.frame.width, rowHeight))
                v.backgroundColor = UIColor.yellowColor()
                let im = UIImageView(frame: CGRectMake(0, CGFloat(i)*imageHeight, imageWidth, imageHeight ))
                //print("expertise image path: ", e.getImagePath())
                im.af_setImageWithURL(
                    NSURL(string: e.getImagePath())!,
                    placeholderImage: UIImage(named: "default_galary_demo2")!
                )

                im.translatesAutoresizingMaskIntoConstraints = false
                v.addSubview(im)

                // Adding constraints
                NSLayoutConstraint(item: im, attribute: .CenterY, relatedBy: .Equal, toItem: v, attribute: .CenterY, multiplier: 1, constant: 0).active = true
                NSLayoutConstraint(item: im, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: v, attribute: NSLayoutAttribute.LeadingMargin, multiplier: 1.0, constant: 0.0).active = true
                im.widthAnchor.constraintEqualToAnchor(nil, constant: imageWidth).active = true
                im.heightAnchor.constraintEqualToAnchor(nil, constant: imageHeight).active = true

                // cell.frame.width - im.frame.width - 50
                let label = UILabel(frame: CGRectMake(0, CGFloat(i)*labelHeight, UIScreen.mainScreen().bounds.width - imageWidth, labelHeight))
                label.font = UIFont(name: "OpenSans", size: 12)
                print("expertise dump:  ", dump(e.getExpertiseValuesList()))
                //print("expertise str: ", e.getExpertiseValuesList().map({"\($0.getName())"}).joinWithSeparator(","))
                label.text = e.getExpertiseValuesList().map({"\($0.getName())"}).joinWithSeparator(",")

                //label.translatesAutoresizingMaskIntoConstraints = false
                v.addSubview(label)


                NSLayoutConstraint(item: label, attribute: .CenterY, relatedBy: .Equal, toItem: v, attribute: .CenterY, multiplier: 1, constant: 0).active = true

                NSLayoutConstraint(item: label, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: im, attribute: NSLayoutAttribute.LeadingMargin, multiplier: 1.0, constant: 10.0).active = true

                cell.designerExpertiseView.addSubview(v)
                i += 1
            }
            self.firstRender[indexPath.section] = false

3 个答案:

答案 0 :(得分:0)

我不认为仅在if self.firstRender[indexPath.section]时呈现单元格是正确的,因为当用户滚动表视图时,屏幕外的单元格将被重用以显示其他不同的indexPath。  另一件事,你创建约束,但不使用它们

答案 1 :(得分:0)

您可以使用UIStackViews来处理约束。你会:

  1. 大大减少班级中的样板约束代码;
  2. 简化添加子视图;
  3. 允许自适应布局。
  4. 在UITableViewCell中添加一个垂直UIStackViewFor。对于更复杂的布局,您可以将更多UIStackView嵌入到Vertical堆栈视图中,也可以混合使用AutoLayout和UIStackViews。

    Using a UIStackView

    我很快就尝试重新创建您的布局,并且我添加了一个UIStackView。此实现将AutoLayout用于某些 fixed 组件(如配置文件图片)和堆栈视图以处理以编程方式添加的UILabel。

    我希望这有帮助!

答案 2 :(得分:0)

看起来,使用.addSubView()以编程方式将视图添加到单元格对于可重用单元格而言并不顺利。之所以发生这种情况,是因为单元格在离开视图时会被重复使用,但当再次变为可见时,会再次添加子视图。

我使用的解决方案/解决方法是从故事板添加另一个占位符视图。我在不需要时使用.removeFromSuperview()从superview中删除了视图。

我知道这种方法并不好 例如:假设我在一个单元格中放置了10个视图(假设10是我需要的最大视图),但根据我从服务器获得的数据,可能不需要其中的许多视图。所以我将从视图中删除大部分内容。

我仍在为这个问题寻找更好/实际的解决方案。