【问题标题】:Glitch in UITableView when UIBarButtonItem is animatedUIBarButtonItem 动画时 UITableView 中的故障
【发布时间】:2019-02-13 10:57:27
【问题描述】:

当 CloudKit 同步成功时,我使用第二个右栏按钮项作为指示器。但是,如果当指示器出现时 tableView 处于滚动状态(现在项目位于导航栏下方),则 tableView 会与动画同步弹跳。如果用户没有与 tableView 交互,则不会发生这种情况。

这是一个演示效果的 GIF。

其他UIBarButtonItems 在情节提要中设置。我的 iCloud 同步指示器是在 viewDidLoad() 中的代码中设置的:

var cloudIndicator = UIImageView()
cloudIndicator.frame = CGRect(x: 0, y: 0, width: 25, height: 25)
cloudIndicator.contentMode = .center
cloudIndicator.transform = CGAffineTransform.identity
// Get existing right bar button item which was set up in storyboard
var rightButtonItems = self.navigationItem.rightBarButtonItems ?? []
let customButtonItem = UIBarButtonItem(customView: cloudIndicator)
rightButtonItems.append(customButtonItem)
self.navigationItem.rightBarButtonItems = rightButtonItems

这是为云同步指示器设置动画的方法:

func cloudLabelImageAlert(_ image: UIImage, tintColor: UIColor = .darkGray) {
    DispatchQueue.main.async {
        self.cloudIndicator.alpha = 0
        self.cloudIndicator.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
        self.cloudIndicator.tintColor = tintColor
        self.cloudIndicator.image = image
        // Animate icon appearing
        UIView.animate(withDuration: 0.4, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 10, options: [], animations: {
            self.cloudIndicator.alpha = 1
            self.cloudIndicator.transform = CGAffineTransform.identity
        }, completion: { didFinish in
            // Animate icon disappearing
            UIView.animate(withDuration: 0.4, delay: 2.0, usingSpringWithDamping: 1.0, initialSpringVelocity: 0, options: [], animations: {
                self.cloudIndicator.alpha = 0
                self.cloudIndicator.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
            }, completion: nil)
        })
    }
)

大概这个问题与动画期间图像视图的框架变化有关,但奇怪的是它只在与 tableView 交互时发生。

有没有办法防止这种情况发生,或者有更好的方法将图像视图动画化为条形按钮项?


编辑

感谢 cmets 中的建议,事实证明这是由于重新加载 tableview 而与动画无关。

我发现有问题的代码在 CloudKit 同步后调用:

if let index = self.tableView.indexPathForSelectedRow {
    self.tableView.deselectRow(at: index, animated: true)
    DispatchQueue.main.asyncAfter(deadline: .now()+1) {
        self.tableView.reloadData() // This is delayed as it was causing problems with autoselection (e.g. after coming from Spotlight or notification)
        let image = UIImage(named: "cloudTick")!
        self.cloudLabelImageAlert(image, tintColor: self.colors[0])
    }
} else {
    self.tableView.reloadData()
    let image = UIImage(named: "cloudTick")!
    self.cloudLabelImageAlert(image, tintColor: self.colors[0])
}

注释掉self.tableview.reloadData() 行停止了故障,但动画按预期继续。

此时我需要为用户更新数据。有没有更好的方法来做到这一点?

【问题讨论】:

  • 因为 tableView 在同步时会重新加载其单元格。
  • @Carpsen90 谢谢。我会检查一下,但这只会在成功同步后触发(不是在重新加载时,尽管我会检查一下),并且在动画期间,故障似乎与动画同步。重新加载肯定只是一个时间点吗?
  • 你能分享你使用cloudLabelImageAlert的代码吗?会有帮助的。
  • @PranavKasetti 稍后我会在我回到我的电脑前分享这个。谢谢
  • @Chris 你确定在加载新表格单元格时没有调用cloudLabelImageAlert(image:, tintColor:) 方法吗?

标签: ios swift uitableview cocoa-touch uibarbuttonitem


【解决方案1】:

似乎出于某种神秘原因,您的导航栏会暂时显示“大标题”,这会导致 tableView 的 contentInset 发生变化。
所以尝试在 viewDidLoad 中手动禁用大标题:

if #available(iOS 11.0, *) {
     navigationItem.largeTitleDisplayMode = .never
     navigationController?.navigationBar.prefersLargeTitles = false
}

【讨论】:

  • 嗨。感谢您的回答。大标题是故意的。 gif 中的第一个动作是我手动滚动 tableView。之后的生涩动作就是问题所在。
【解决方案2】:

如评论部分所述,您可能在加载新表格单元格时调用cloudLabelImageAlert(image:, tintColor:) 方法。

关于更新数据,我建议在云动画完成后调用表格视图reloadData() 方法。

【讨论】:

  • 谢谢。您完全正确的是重新加载 tableView 导致了故障而不是动画!
【解决方案3】:

您好,我遇到了不一样的类似故障,但对我来说,通过在 viewDidLoad 中将 self.automaticallyScrollInsets 设置为 false 并在最后的 UIView.animate 完成块中为 imageView 设置动画以隐藏和显示,我称之为 reloadData()。希望这会有所帮助,谢谢!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-09-27
    • 2014-11-24
    • 2013-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-23
    相关资源
    最近更新 更多