Ios 为什么从NotificationCenter调整标签大小时需要延迟才能按预期更新?
我正在将动态类型添加到我的应用程序中,当通过以下代码触发Ios 为什么从NotificationCenter调整标签大小时需要延迟才能按预期更新?,ios,swift,multithreading,uikit,uilabel,Ios,Swift,Multithreading,Uikit,Uilabel,我正在将动态类型添加到我的应用程序中,当通过以下代码触发UIContentSizeCategoryDidChangeNotification通知时,我正在尝试更新以编程方式创建的UILabel的框架: private func configureNotificationCenter() { NotificationCenter.default.addObserver(self, selector: #selector(contentSizeCategoryDidChange) , nam
UIContentSizeCategoryDidChangeNotification
通知时,我正在尝试更新以编程方式创建的UILabel的框架:
private func configureNotificationCenter() {
NotificationCenter.default.addObserver(self, selector: #selector(contentSizeCategoryDidChange) , name: NSNotification.Name("UIContentSizeCategoryDidChangeNotification"), object: nil)
}
@objc private func contentSizeCategoryDidChange() {
self.delegate?.didChangeContentSize()
}
然后在要更新UILabel的视图中,我更新了框架:
func didChangeContentSize() {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1, execute: {
self.label.sizeToFit()
})
}
由于某些原因,如果不调用DispatchQueue.main.asyncAfter…
,则无法正确设置帧。起初,我尝试调用DispatchQueue.main
,没有0.1秒的延迟,因为我知道UI更新应该始终在主线程上,但这似乎没有任何区别
虽然延迟0.1秒并不是什么大问题,我不认为任何用户会注意到,但了解发生了什么以及为什么需要延迟会很好
编辑:以下是我创建标签的方式
label = UILabel(frame: CGRect(x: 0, y: 100, width: view.frame.width, height: 200))
label.backgroundColor = .red
label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping
label.text = "Test title that should resize"
label.adjustsFontForContentSizeCategory = true
label.textAlignment = .center
let userFont = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .title1)
let pointSize = userFont.pointSize
let customFont = UIFont(name: "AvenirNext-DemiBold", size: pointSize)
label.font = UIFontMetrics.default.scaledFont(for: customFont!)
label.sizeToFit()
view.addSubview(label)
这听起来很像一个自动布局问题。如果不延迟,自动布局将调整标签的固有大小,并在修改标签的框架后运行,因此您的
sizeToFit
来得太早,并使用以前的固有大小
当您延迟0.1秒时,自动布局将首先运行并设置标签的固有大小,然后您的sizeToFit()
调用将使用该新的固有大小来设置帧
使用自动布局 通过使用自动布局,让事情变得更简单。只需为标签的前缘、后缘和顶边设置约束,自动布局将在字体大小更改时自动调整标签大小,而不必处理
边框
大小、sizeToFit
和通知:
label = UILabel()
label.backgroundColor = .red
label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping
label.text = "Test title that should resize"
label.adjustsFontForContentSizeCategory = true
label.textAlignment = .center
let userFont = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .title1)
let pointSize = userFont.pointSize
let customFont = UIFont(name: "AvenirNext-DemiBold", size: pointSize)
label.font = UIFontMetrics.default.scaledFont(for: customFont!)
view.addSubview(label)
label.translatesAutoresizingMaskIntoConstraints = false
label.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
label.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
label.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
奇怪的是,我已经以编程方式创建了标签。我将更新我的问题以反映这一点。更新代码以显示标签的创建。另外,您在哪里更新标签的文本以使调整大小成为必要?我刚刚编辑了我的问题以显示标签的创建。文本不会更改,
UIContentSizeCategoryDidChangeNotification
在用户从设置更改其字体大小首选项时被调用。在调用self.label.layoutSubviews()之前调用self.label.sizeToFit()
是否有效?我已更新了答案,以显示更简单的自动布局方法。我知道你在幕后的问题是自动布局,也许有办法让它工作,但更简单的方法是采用自动布局。这样,您就不必处理通知了。您是否尝试过systemLayoutSizeFittingSize
?这可能对你的案子有好处