Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 为什么从NotificationCenter调整标签大小时需要延迟才能按预期更新?_Ios_Swift_Multithreading_Uikit_Uilabel - Fatal编程技术网

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
?这可能对你的案子有好处