Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is frame width of the view alway 600 by 600 with autolayout

I am making a basic Minesweeper app for practice / fun in swift. I want to make it so the size of the board (10 tiles wide) adapts to any iOS screen.

To do this I'm setting the size of each tile by getting my tileContainer view.frame.width and / 10.

My problem is that the tileContainer view is set to 600, no matter what. On my Storyboard I set the tileContainer equal to the width of the View Container, by CTR click & dragging to the view and selecting equal width. This keeps the width of tileContainer set at 600, regardless of the device I'm testing on. (which is my problem, width should change depending on screen width not a constant 600)

Does anyone know how I can get the proper width of the screen regardless of the device it's being used on?

like image 623
Evan Nudd Avatar asked May 14 '15 02:05

Evan Nudd


3 Answers

When you are using auto-layout, the subviews are laid out after the viewDidLayoutSubviews function. Therefore, if you call tileContainer.frame.size before that, such as in viewDidLoad, it will always be 600 by 600 (which is the default size in storyboard).

viewDidLayoutSubviews: Called to notify the view controller that its view has just laid out its subviews. reference

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    print(tileContainer.frame.size); // This is actual size you are looking for
}
like image 77
Yuchen Avatar answered Nov 15 '22 13:11

Yuchen


Short answer: UIScreen.mainScreen().bounds.size.width always returns the width of the screen.

Long answer: It sounds like you are using auto layout with size classes. You can make this all work just using constraints. You can set a proportional width and height constraint from your tile to your container so that the tile is 10% of the width and height of the container. Then, you can set all the other tiles to have equal width and height to that one tile. Then, use constraints to position them in a grid.

Another strategy using autolayout would be to set the spacing between the cells to be 0 and leave the width and height unconstrained. If you have 10 cells with 0 space between the cells and eachother, and 0 space between the front and back cells and the container, then they will automatically take on the 1/10 of the width of the container.

Additional note, if using size classes/auto layout, the view size is not properly set until subviews are laid out, so if you are trying to do this width stuff in viewDidLoad, for example, the width would still be the width of the Any Any size class (600).

like image 43
Will M. Avatar answered Nov 15 '22 14:11

Will M.


While the accepted answers is a correct answer I thought I might at least say that you can force the view to draw itself before hitting viewDidAppear:.

Either, you can in your viewDidLoad: call:

view.setNeedsLayout()
view.layoutIfNeeded()

Or if you create it from "outside":

let vc = UIViewController()
let _ = vc.view

or

let vc = UIViewController()
vc.view.setNeedsLayout()
vc.view.layoutIfNeeded()

like image 4
user023 Avatar answered Nov 15 '22 14:11

user023