0

Before presenting my GameScene I apply the safeAreaLayoutGuide to the initial view screen (code below is from GameViewController).

If at any point before I call view.presentScene(scene) I try to get the view's frame, I get back an empty set.

If however I get the frame, after presenting the scene, I get the rect for the full screen, even though the view does appear within the safeAreaLayoutGuide.

How can I get the view's safe adjusted screen coordinates? I should note I am doing this so I can apply the proper constraints to my GameScene, as I can only find how to do it for UIView.

class GameViewController: UIViewController {
    override func viewDidLoad() {
    super.viewDidLoad()

    if let view = self.view as! SKView?{
        let screenWidthInPoints = UIScreen.main.bounds.width
        let screenHeightInPoints = UIScreen.main.bounds.height

        let imageView = UIView()
        imageView.backgroundColor = .red
        view.addSubview(imageView)

        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true
        imageView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
        imageView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor).isActive = true
        imageView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor , constant: -0).isActive = true



        let scene = GameScene(size: CGSize(width: screenWidthInPoints,
        height: screenHeightInPoints))
        scene.backgroundColor = .black
        scene.scaleMode = .aspectFit
        view.presentScene(scene)
        var myRect = view.frame
Caractacus
  • 83
  • 7

1 Answers1

3

UIScreen.main.bounds represents the entire screen, not just the safe area. You will have to create a separate view constrained to safe area insets to get the proper safe area size. In your case, you already have an imageView placed within the safe area. Try printing out its size after adding the constraints and do it within a DispatchQueue.main.async to make sure that it gets called only after the current pass layout is complete.

    let imageView = UIView()
    imageView.backgroundColor = .red
    view.addSubview(imageView)
    
    imageView.translatesAutoresizingMaskIntoConstraints = false
    imageView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true
    imageView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
    imageView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor).isActive = true
    imageView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor , constant: -0).isActive = true
    
    
    DispatchQueue.main.async {
        print("imageView.frame: ", imageView.frame)
        
        let scene = GameScene(size: CGSize(width: imageView.frame.width,
                                           height: imageView.frame.height))
        scene.backgroundColor = .black
        scene.scaleMode = .aspectFit
        view.presentScene(scene)
    }
Jithin
  • 913
  • 5
  • 6
  • This is much closer, I get the proper dimensions. However DispatchQueue.main.async returns so much later, am going to have to find a way to delay the GameScene being presented till the Queue returns and pass the numbers. No resolved yet, but the closest I have come so far – Caractacus Aug 14 '20 at 05:25
  • Your queue answer got me close. Sometimes the width comes back as zero thought (and I do wait for the queued code to complete) so I'll have to make sure I check the width carefully. Thank you – Caractacus Aug 17 '20 at 04:24