layoutIfNeeded函数行为

时间:2016-12-26 13:29:08

标签: ios swift layout

我正在使用这个函数进行大量的渐变绘制:

func drawGradient(colors: [CGColor], locations:  [NSNumber]) {
    let gradientLayer = CAGradientLayer()
    gradientLayer.frame.size = self.frame.size
    gradientLayer.frame.origin = CGPoint(x: 0.0,y: 0.0)
    gradientLayer.colors = colors
    gradientLayer.locations = locations
    print(self.frame.size)
    self.layer.insertSublayer(gradientLayer, at: 0)
}

问题在于,如果我不在self.view.layoutIfNeeded()的{​​{1}}中拨打viewDidLoad()我的渐变不会覆盖iPhone X +上的整个屏幕。但是,如果我打电话给UIViewController,它会让我的应用程序在iOS 9.x上崩溃并在iPhone 5/5上表现得很奇怪。我真的不知道任何解决方法,需要帮助才能理解它是如何工作的。

1 个答案:

答案 0 :(得分:2)

您正在drawGradient中呼叫viewDidLoad。那太早了。您需要等到自动布局确定框架大小。 将viewDidLoad中的来电移至viewDidLayoutSubviews的覆盖。但要小心,因为viewDidLayoutSubviews被多次调用,所以请确保只调用drawGradient一次。您可以向viewController添加一个名为var appliedGradient = false的属性,然后在应用渐变之前检查它并将其翻转到true

对于UITableViewCellUICollectionViewCell的自定义子类,请覆盖layoutSubviews并在drawGradient后调用super.layoutSubviews()。再次确保你只调用一次。

注意:如果frame可以调整大小(由于手机的旋转)或不同的单元格大小,您应该跟踪上一个渐变图层并将其替换为新图层在viewDidLayoutSubviews中为您的viewController和layoutSubviews为您的单元格。

我在这里修改了您的drawGradient,以创建一个名为applyGradient的全局函数,为视图添加渐变。如果有一个渐变图层,它将替换先前的渐变图层:

func applyGradient(colors: [CGColor], locations: [NSNumber], to view: UIView, replacing prior: CALayer?) -> CALayer {
    let gradientLayer = CAGradientLayer()
    gradientLayer.frame.size = view.frame.size
    gradientLayer.frame.origin = CGPoint(x: 0.0,y: 0.0)
    gradientLayer.colors = colors
    gradientLayer.locations = locations
    print(view.frame.size)
    if let prior = prior {
        view.layer.replaceSublayer(prior, with: gradientLayer)
    } else {
        view.layer.insertSublayer(gradientLayer, at: 0)
    }
    return gradientLayer
}

它的用法如下:

class ViewController: UIViewController {
    // property to keep track of the gradient layer
    var gradient: CALayer?

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        gradient = applyGradient(colors: [UIColor.red.cgColor, UIColor.yellow.cgColor],
            locations: [0.0, 1.0], to: self.view, replacing: gradient)
    }
}