将新单元格插入表视图时,在所有可见单元格上该怎么称呼?

时间:2019-04-05 18:40:01

标签: ios uitableview

我正在创建一个表格视图,允许用户在我的应用程序中的帖子上发表评论。创建新评论时,我正在使用UITableView.insertRows(at:with :)方法在其相应位置添加新评论单元。

单元格已正确添加到表视图中,但所有其他可见单元格均已调整了其子视图,即,其约束已重置为UITableViewCell的默认约束。每当我最初使单元出队时,我都会调用cell.layoutSubviews来设置单元的约束。插入新单元格后,此操作将撤消。

我发现,每当插入一个新单元格时,其他可见单元格都不会调用cellForRow(at :)。我很好奇,每当插入新单元格时,在其他可见函数上调用了什么函数 。这样,我可以布局各个已经存在的单元的子视图来解决此问题。您会看到,当我“喜欢”评论时,单元的子视图会适当地布局。这是因为只要按下like按钮,就会调用cell.layout子视图。

我分别在插入之前和之后使用UITableView.beginUpdates()和UITableView.endUpdates,当然,不可见的单元格不受插入的影响,因为它们的子视图在出队时会被布局。

总而言之,我只需要知道在将新单元格插入表视图后在可见的,已经存在的单元格上正在调用什么函数。

这样可以将您导航到有关我的问题的视频:https://www.youtube.com/watch?v=7MUr5C9Oj0c&feature=youtu.be

(保罗的约束代码)

//The following is called on initialization
let viewsDict = ["contentView":contentView,"imageView":imageView,"textLabel":textLabel,"detailTextLabel":detailTextLabel,"timeLabel":timeLabel,"likesLabel":likesLabel,"likeButton":likeButton,"replyButton":replyButton] as [String:Any]

    //Horizontal constraints
    contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[imageView(35)]-[textLabel]-[likeButton(50)]-(-2)-|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: viewsDict))

    contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[imageView(35)]-[detailTextLabel]-|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: viewsDict))

    contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[imageView(35)]-[timeLabel]-[likesLabel]-[replyButton]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: viewsDict))

    //Vertical constriants
    contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-[imageView(35)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: viewsDict))

    contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-(-2)-[likeButton(50)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: viewsDict))

    contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-[textLabel]-[detailTextLabel]-[timeLabel]-8-|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: viewsDict))

    contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-[textLabel]-[detailTextLabel]-[likesLabel]-8-|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: viewsDict))

    contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-[textLabel]-[detailTextLabel]-[replyButton]-8-|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: viewsDict))

在layoutSubviews中,我检查注释是答复还是删除,并进行相应调整。回复将带有缩进,原始帖子则不会。删除的帖子对约束没有影响。以下是通过layoutSubviews调用的:

//Check if constraints need to be adjusted
    if replyTo != nil && !isDeleted {
        //Is a reply, isn't deleted

        if indentImageView == nil {
            addIndentedConstraints()
        }

    } else if replyTo == nil && isDeleted {
        //Isn't a reply and is deleted

        if indentImageView != nil {
            removeIndentedConstraints()
        }

    } else if replyTo == nil && !isDeleted {
        //Isn't a reply and isn't deleted

        if indentImageView != nil {
            removeIndentedConstraints()
        }

    } else if replyTo != nil && isDeleted {
        //Is a reply, is deleted

        if indentImageView == nil {
            addIndentedConstraints()
        }

    }

然后添加缩进约束或非缩进约束的函数:

func addIndentedConstraints() {
    indentImageView = UIImageView(image: UIImage(named: "indent")?.resize(targetSize: CGSize(width: 36, height: 18)))
    contentView.addSubview(indentImageView!)
    indentImageView!.translatesAutoresizingMaskIntoConstraints = false
    let viewsDict = ["contentView":contentView,"indentImageView":indentImageView,"imageView":imageView,"textLabel":textLabel,"detailTextLabel":detailTextLabel,"timeLabel":timeLabel,"likesLabel":likesLabel,"likeButton":likeButton,"replyButton":replyButton,] as [String:Any]

    let indentedConstraints1 = NSLayoutConstraint.constraints(withVisualFormat: "H:|-67.5-[imageView(35)]-[textLabel]-[likeButton(50)]-(-2)-|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: viewsDict)
    indentedConstraints1.giveAllConstraints(identifier: "indentedConstraint")
    contentView.addConstraints(indentedConstraints1)

    let indentedConstraints2 = NSLayoutConstraint.constraints(withVisualFormat: "H:|-25.5-[indentImageView(36)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: viewsDict)
    indentedConstraints2.giveAllConstraints(identifier: "indentedConstraint")
    contentView.addConstraints(indentedConstraints2)

    let indentedConstraints3 = NSLayoutConstraint.constraints(withVisualFormat: "V:|-[indentImageView(18)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: viewsDict)
    indentedConstraints3.giveAllConstraints(identifier: "indentedConstraint")
    contentView.addConstraints(indentedConstraints3)

    let indentedConstraints4 = NSLayoutConstraint.constraints(withVisualFormat: "V:|-[imageView(35)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: viewsDict)
    indentedConstraints4.giveAllConstraints(identifier: "indentedConstraint")
    contentView.addConstraints(indentedConstraints4)
}

func removeIndentedConstraints() {
    indentImageView!.removeFromSuperview()
    indentImageView = nil

    //Loop through all of our contentview's constraints and check if the constraint is an indentedConstraint. Remove this constraint if it is
    for constraint in contentView.constraints {
        if constraint.identifier == "indentedConstraint" {
            contentView.removeConstraint(constraint)
        }
    }
    let viewsDict = ["contentView":contentView,"imageView":imageView,"textLabel":textLabel,"detailTextLabel":detailTextLabel,"timeLabel":timeLabel,"likesLabel":likesLabel,"likeButton":likeButton,"replyButton":replyButton,] as [String:Any]
    contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[imageView(35)]-[textLabel]-|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: viewsDict))
}

[NSLayoutConstraint] .giveAllConstraints(identifier :)自然为NSLayoutConstraint数组中的所有元素赋予相同的标识符。这样,我可以遍历并检查约束是否为缩进约束,然后仅在需要时才删除约束。

1 个答案:

答案 0 :(得分:0)

我最终发现的是,仅在调用tableView.insertRows时在要插入的单元格上调用cellForRow。在tableView.endUpdates之前调用tableView.reloadRows并传递所有可见单元格的索引路径会导致我的所有可见单元格重新加载并自然地布局其子视图。

初始代码:

self!.tableView.beginUpdates()
self!.tableView.insertRows(at: [indexPath], with: .none)
self!.tableView.endUpdates()

有效的代码:

self!.tableView.beginUpdates()
self!.tableView.insertRows(at: [indexPath], with: .none)
self!.tableView.reloadRows(at: self!.tableView.indexPathsForVisibleRows!, with: .none)
self!.tableView.endUpdates()