4

The issue I'm having is that the label is anchored to the bottom edge of the screen when it should be anchored to the safe area layout guide. which will bring the label above the iPhone line.

Here's the code...

class CustomTableViewController: UITableViewController {

   override func viewDidLoad() {
       super.viewDidLoad()

       tableView.tableFooterView = UIView(frame: .zero)
       tableView.backgroundView = CustomBackgroundView()
   } 

}

.

class CustomBackgroundView: UIView {

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

   required init?(coder aDecoder: NSCoder) {
       fatalError("init(coder:) has not been implemented")
   }

   private func setupSubviews() {
       let label = UILabel()
       label.text = "Hello, World!"
       label.textAlignment = .center
       label.translatesAutoresizingMaskIntoConstraints = false

       addSubview(label)

       label.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
       label.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor).isActive = true
   } 

}

enter image description here

dispatchswift
  • 1,046
  • 9
  • 21

2 Answers2

0

You are seeing this behavior because every UIView has its own SafeAreaLayoutGuide. Per default the SafeAreaLayoutGuide of a generic UIView subclass does not include the Safe Areas that you are looking for. You have to use the SafeAreaLayoutGuide of your table view.

You could do something like this:

class CustomBackgroundView: UIView {

    var safetyAreaBottomAnchor: NSLayoutYAxisAnchor? {
        didSet {
            guard let safetyAreaBottomAnchor = safetyAreaBottomAnchor else { return }
            label.bottomAnchor.constraint(equalTo: safetyAreaBottomAnchor).isActive = true
        }
    }

    private let label = UILabel()

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

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func setupSubviews() {
        label.text = "Hello, World!"
        label.textAlignment = .center
        label.translatesAutoresizingMaskIntoConstraints = false

        addSubview(label)

        label.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
    } 
}

And then in your UITableViewController do this:

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    let customBackgroundView = CustomBackgroundView()
    tableView.tableFooterView = UIView(frame: .zero)
    tableView.backgroundView = customBackgroundView

    customBackgroundView.safetyAreaBottomAnchor = tableView.safeAreaLayoutGuide.bottomAnchor
}
joern
  • 27,354
  • 7
  • 90
  • 105
0

For anyone arriving from Google after all these years, to get this to work I had to return the safeAreaLayoutGuide of the superview from my custom view. See below:

class CustomBackgroundView: UIView {
    override var safeAreaLayoutGuide: UILayoutGuide {
        guard let superview = superview else { return UILayoutGuide() }
        return superview.safeAreaLayoutGuide
    }
}

This made all the constraints work as expected. Make sure you don't use the safeAreaLayoutGuide before adding the background view

func setupBackgroundViews()
{
    tableView.backgroundView = customBackgroundView
    anotherView.topAnchor.constraint(equalTo: customBackgroundView.safeAreaLayoutGuide.topAnchor).isActive = true
}
derickito
  • 695
  • 7
  • 25