gpt4 book ai didi

ios - 当应用程序进入后台状态时重复调用 layoutSubviews

转载 作者:搜寻专家 更新时间:2023-11-01 06:19:14 29 4
gpt4 key购买 nike

我希望标签的字体大小与屏幕大小成正比。我已将 UILabel 类子类化以实现此目的:

@IBDesignable class MyCustomLabel: UILabel {
override func layoutSubviews() {
super.layoutSubviews()
self.font = UIFont(name: "myFontName", size: (self.font?.pointSize)!)
self.adjustsFontSizeToFitWidth = true
}
}

当应用程序首次启动时,标签(具有与附加到它们的 super View 约束成比例的宽度)会正确调整大小,但当它进入后台状态时,layoutSubviews 会被重复调用。该应用程序不再响应用户的输入并不断为字体分配字体大小。

为什么会这样?

最佳答案

在您的测试项目中,如果我在 iPhone 上运行,我没有看到 layoutSubviews() 在后台被调用。它只发生在 iPad 上。

那是因为您的应用支持多任​​务处理:

  • 当您的应用停用时,iOS 会将其调整为不同的大小,以便为应用切换器拍摄快照。这些调整大小会导致调用 View 的 layoutSubviews()。这是完全正常的。
  • 然后 iOS 会将您的应用恢复为原始大小。

真正的问题是您正在创建一个“布局循环”。您在 layoutSubviews() 中的代码导致您自己的 View 布局失效,因此系统需要再次运行布局过程。然后布局运行,你再做一次,它会再次发生。

具体原因是:

self.font = UIFont(name: fontName, size: fontSize)

更改标签的字体会导致其 intrinsicSize 发生变化,这意味着其父 View 可能需要更新其布局,因此布局过程需要再次运行。在 layoutSubviews() 中执行此操作是个坏主意,因为它会导致布局循环。您实际上应该只更改 subview 的属性,而不是 View 本身。

为什么您认为您需要在 layoutSubviews() 中执行此操作?在布局过程之外,可能有一个更好的地方来放置它。在您的示例中,我根本看不出这段代码如何做任何有用的事情。

设置adjustsFrameSizeToWidth 一次,然后在layoutSubviews() 中不做任何事情会更有意义:

override init(frame: CGRect) {
super.init(frame: frame)
self.adjustsFontSizeToFitWidth = true
}

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.adjustsFontSizeToFitWidth = true
}

如果您尝试根据大小类更改字体大小,您可以通过重写 traitCollectionDidChange() 在代码中完成此操作:

override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)

var fontSize: CGFloat
if (self.traitCollection.horizontalSizeClass == .Regular) {
fontSize = 70
}
else {
fontSize = 30
}
self.font = UIFont(name: fontName, size:fontSize)
}

关于ios - 当应用程序进入后台状态时重复调用 layoutSubviews,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37487446/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com