【问题标题】:When is view frame size set in iOS10 SDK?iOS10 SDK什么时候设置view frame size?
【发布时间】:2017-01-19 15:46:53
【问题描述】:

多年来,我在 Swift 和 ObjC 中一直使用这种技术来制作圆形视图:

view.layer.cornerRadius = view.frame.size.width / 2
view.clipsToBounds = true

当故事板中的 UILayoutConstraints 是固定宽度/高度时,将此代码放入 viewDidLoad 或 viewWillAppear 中没有问题。内置iOS9.3SDK,在iOS10等环境下运行良好

iOS10SDK 显示的帧大小与 Storyboard 中的固定大小完全不同,甚至达到 viewWillAppear 和 viewDidLayoutSubviews 等。我的选择是:

1) 在 vi​​ewDidAppear 中执行此操作(糟糕的解决方案) 2)硬编码cornerRadius(工作正常,但很糟糕)

这看起来像一个错误(因为在 Storyboard 中设置的固定宽度/高度不应该在没有控制台警告的情况下更改)。是它,还是现在这个代码有不同的地方? (附上测试代码截图)

【问题讨论】:

  • 我所有的 IB 生成的视图在 viewDidLoad 和代码的许多其他部分都有新的未初始化帧大小 {1000,1000}。包括 cellForRowAtIndexPath
  • 我发现直接使用约束宽度/高度而不是框架宽度高度是一个合理的解决方案。 stackoverflow.com/questions/39475456/…
  • 嗨@Miro - 正是我所看到的(默认1000)。我也直接设置高度。我也遇到了与 NSLayoutConstraints 相关的问题,这意味着 Apple 在视图布局代码中更改了一堆东西 :-)

标签: autolayout ios10


【解决方案1】:

在 iOS 10 中,我在 6 月份开始使用 Xcode 8 后就遇到了这个问题,当时它是 beta 版本。需要这个解决方案:

layoutIfNeeded() 放在图层修改之前:

self.view.layoutIfNeeded()

view.layer.cornerRadius = view.frame.size.width / 2
view.clipsToBounds = true

将圆角半径的代码放到viewDidLayoutSubviews()方法中:

override func viewDidLayoutSubviews() {

    view.layer.cornerRadius = view.frame.size.width / 2
    view.clipsToBounds = true

}

【讨论】:

    【解决方案2】:

    今天这件事困扰了我一整天。我在几个方面遇到了同样的问题,我需要正确的帧大小来绘制自定义 UI 元素,或将样式应用于视图,尤其是更改角半径。我找到的解决方案是使用以下实现创建 UIViewController 的子类:

    class BaseViewController: UIViewController {
    
        /** 
            This is a helper property and a helper method that will be called
            when the frame is calculated, but will prevent the formatting code
            being called more than once
        */
        private var didCalculateInitialFrame = false
        private func checkIfFrameWasCalculated() {
            if self.didCalculateInitialFrame == false {
                self.viewDidCalculateInitialFrame()
                self.didCalculateInitialFrame = true
            }
        }
    
        //-- This is where you will tie your helper method with the view lifecycle
        override func viewDidLayoutSubviews() {
            super.viewDidLayoutSubviews()
            self.checkIfFrameWasCalculated()
        }
    
        /** 
            This is an overridable function that you will implement 
            in your subclasses, in case you need to use this approach
            in multiple places of your app. 
        */
        func viewDidCalculateInitialFrame() {
    
        }
    }
    

    这解决了我对故事板的所有问题。我希望这是有帮助的。

    【讨论】:

    • 嗨,亚历克斯 - 这非常有帮助(赞成)。我只是推迟接受作为答案,因为我觉得必须有一个“正确”的方法来做到这一点,这感觉就像一个临时的解决方法。非常感谢您的回答。
    • 彼得,谢谢 - 与你同在!如果记录了正确的方法,我肯定会更新这个答案。无论如何,我分享了我用来玩新视图控制器生命周期的项目,以及在 iOS 10 / Xcode 8.0 GM 中如何以及何时计算视图帧。你可以在这里找到它:link.
    【解决方案3】:

    这似乎是 ios10 中的问题

    可以通过重写控制器方法 viewDidLayoutSubviews() 或 为视图调用方法 layoutIfNeeded() 在获取其维度之前您可能需要哪个维度值。 Objective-C :[viewObject layoutIfNeeded] 斯威夫特:viewObject.layoutIfNeeded()

    如果尺寸值仍然不正确,则对视图对象的父视图使用 layoutIfNeeded 方法。

    【讨论】:

      猜你喜欢
      • 2012-03-03
      • 1970-01-01
      • 1970-01-01
      • 2010-11-07
      • 2021-07-28
      • 1970-01-01
      • 2011-05-15
      • 2020-03-15
      • 1970-01-01
      相关资源
      最近更新 更多