【问题标题】:How to be notified when a UIView is fully loaded如何在 UIView 完全加载时收到通知
【发布时间】:2017-08-01 05:15:23
【问题描述】:

我有一个 UIView 添加到 UIViewController,我想确保视图已完全加载,因为我想访问和使用这些视图的框架。我在 UIView 中工作,而 ViewController 仅用于测试目的。

这是我正在使用的示例:

我正在将自定义 UIView 加载到 UIViewController 中,因此我将按以下方式初始化视图:

在 UIViewController 中

var slideView: BSlideBar = BSlideBar(frame: CGRect(x: 0, y: 150, width: 320, height: 54))

self.view.addSubview(slideView)

在 UIView 中

override init(frame: CGRect) {
    super.init(frame: frame)    
    customInit()
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    customInit()
}

public func customInit() {

    Bundle.main.loadNibNamed("BSlideBar", owner: self, options: nil)
    self.addSubview(self.slideView)
    self.slideView.frame = self.bounds
}

我有一个与我的 UIView 关联的 XIB 文件,所以我在自定义初始化函数中加载 Nib。

这个 UIView 里面还有其他的 UIView,都被添加到 UIViewController 中。这一切正常,当我尝试访问这些视图的属性时出现问题:

例子:

draggableView.layer.cornerRadius = draggableView.frame.width/2

这将使 draggableView 成为一个圆圈,并且还允许我将 draggableView 的大小基于它包含在其中的视图,同时将其保持为一个圆圈。这意味着无论我用什么框架初始化它,我的视图都将保持一致。令人讨厌的是,框架总是作为 XIB 文件中的框架返回,而不是加载的 UIView 的框架。 (如果我在加载按钮后单击它,则返回预期和所需的帧)

示例 2:

self.centreLine.frame = CGRect(x: Int(sidePadding), y: Int(slideView.frame.height/2), width: Int(UIScreen.main.bounds.width - 2 * sidePadding), height: 2)

再一次,我希望这个视图能够调整到包含它的视图的大小。在这种情况下,它应该保持在边缘的填充内,并且正好在视图的中间。再一次,情况并非如此。

我曾尝试使用this 回答,方法是:

-(void)awakeFromNib

override func layoutSubviews() {
    super.layoutSubviews()
}

但是这些似乎都没有被调用足够晚。

问题部分是由于在 UIView 内部,因为我通常会这样称呼:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
}

我有点困惑,但我真的很想知道为什么会出现这个问题。我遇到的主要问题是简明扼要地寻找问题并用尽了我目前所有的线索。

【问题讨论】:

标签: swift uiview layoutsubviews


【解决方案1】:

您关心的不是“满载”。它“完全布局”。

覆盖layoutSubviews:

override func layoutSubviews() {
    super.layoutSubviews()

    // At this point, all of my direct subviews' frames are set.
    // However, their subviews (my more distant descendants)
    // haven't had their frames updated yet.
}

没有特别好的方法可以在整个视图层次结构完成布局时得到通知。当您收到drawRect: 时,您可以确定所有后代都已布局,但此时您不应该修改图层属性。

【讨论】:

  • 当我尝试这个时,主 UIView 是由其子视图布局的(正如您的答案中的评论所暗示的那样)。您提到所有后代都将在 drawRect 上布局:在此之前我们是否可以修改图层属性?
【解决方案2】:

在您的视图类中,创建一个加载 nib 并返回加载视图的类函数。使用它来初始化视图

界面视图

class func loadViewFromNib() -> BSlideBar 
    guard let nibs = Bundle.main.loadNibNamed("BSlideBar", owner: self, options: nil) as? [UIVIew] else {  assertFailure(): return UIView() }

    return nibs.first as! BSlideBar
}

在 UIViewVontroller 中初始化变量,配置视图然后将其添加到子视图中

var slideBar: BSlideBar = BSlideBar.loadViewFromNib()
slideBar.frame = CGRect(.....)
addSubview(slideBar)

应该可以,但我会在回答之前仔细检查“为什么”,不想给你坏信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-14
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 2011-01-18
    • 1970-01-01
    • 1970-01-01
    • 2011-05-28
    相关资源
    最近更新 更多