更新UILabel文本时出现问题

时间:2019-03-22 20:07:24

标签: ios swift uilabel

我正在做一个小游戏,但无法更新自己创建的UILabel以显示当前分数。每次尝试更新分数标签时,整个屏幕都会冻结一秒钟,前一帧中的所有对象都会保留在屏幕上,而下一帧将在其上绘制而分数标签不会更新。仅当我尝试更新UILabel时,才会出现此问题,否则一切运行正常,没有任何打ic。

我读到需要在主线程上完成UILabel的更新,并尝试使用Dispatch.main.async进行此操作,但问题仍然存在。在下面,我发布了导致我遇到问题的代码。

fileprivate let scoreLabel: UILabel = {
  let newLabel = UILabel()
  newLabel.textAlignment = .center
  newLabel.textColor = .white
  newLabel.text = "0"
  newLabel.translatesAutoresizingMaskIntoConstraints = false
  return newLabel
}()

var score: Int = 0

fileprivate lazy var displayLink: CADisplayLink = {
  let newLink = CADisplayLink(target: self, selector: #selector(update))
  return newLink
}()

@objc func update() {
  score += 1

  //Method 1: cause screen split second screen lockup
  scoreLabel.text = "\(score)" //doesn't work

  //Method 2: cause screen split second screen lockup
  DispatchQueue.main.async {
    self.scoreLabel.text = "\(score)" //also doesn't work
    self.scoreLabel.setNeedsDisplay()
  }
}

func setupLayout() {
   view.addSubview(scoreLabel)

   NSLayoutConstraint.activate([
     scoreLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor),
     scoreLabel.centerXAnchor.contraint(equalTo: view.centerXAnchor)
     ])
}

override func viewDidLoad() {
   super.viewDidLoad()

   setupLayout()

   displayLink.add(to: .main, forMode: .default)
}

这让我感到困惑,因为此代码在版本4以下的Objective-C和Swift中有效。关于我在做什么的任何想法?

这也是Swift 4.2版本上的

更新:

所以我找到了解决方案。显然,自动布局是造成问题的原因。为了解决这个问题,我发现了两种方法:

  1. 在DispatchQueue.main.async内部,首先停用您的布局约束。然后更新标签并重新激活布局约束并调用layoutIfNeeded()。

  2. 不是使用自动布局,而是使用CGRect手动设置label.frame,并使用label.center和CGPoint手动设置标签的位置。之后,您应该可以更新标签而不会出现问题。

希望这可以帮助可能遇到此问题的其他任何人。

2 个答案:

答案 0 :(得分:0)

显示链接更新用于自定义绘制视图,而不用于更新子视图(它们已经绘制了自己);您是否真的需要每秒重新绘制标签60次?只需更新文本,系统就会将标签标记为脏,并在下一次重绘时解决该问题。您无需强制计时。而且,如果您确实需要类似计数器的内容,则可以使用常规计时器,而不是displaylink计时器。

答案 1 :(得分:0)

尝试layoutIfNeeded()
  layoutIfNeeded强制早期布局

struct hrtimer