我正在做一个小游戏,但无法更新自己创建的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版本上的
更新:
所以我找到了解决方案。显然,自动布局是造成问题的原因。为了解决这个问题,我发现了两种方法:
在DispatchQueue.main.async内部,首先停用您的布局约束。然后更新标签并重新激活布局约束并调用layoutIfNeeded()。
不是使用自动布局,而是使用CGRect手动设置label.frame,并使用label.center和CGPoint手动设置标签的位置。之后,您应该可以更新标签而不会出现问题。
希望这可以帮助可能遇到此问题的其他任何人。
答案 0 :(得分:0)
显示链接更新用于自定义绘制视图,而不用于更新子视图(它们已经绘制了自己);您是否真的需要每秒重新绘制标签60次?只需更新文本,系统就会将标签标记为脏,并在下一次重绘时解决该问题。您无需强制计时。而且,如果您确实需要类似计数器的内容,则可以使用常规计时器,而不是displaylink计时器。
答案 1 :(得分:0)
尝试layoutIfNeeded()
layoutIfNeeded强制早期布局
struct hrtimer