Search code examples
swiftxcodeautolayoutinterface-builder

UIView not adjusting size to match device


Update: I was able to fix my problem below by moving my code in init(coder) to layoutSubviews. Thanks for your input!

I have a view class that basically builds a chess board and has constraints to be 1:1 ratio and a certain number of points from other UI. In the init(coder), I am drawing the board spaces and then calling a function to draw the pieces from my controller.

However, when I run the simulator it will not load based on the device, only on what I currently have selected in Interface Builder.

As an example, I have iPhone 7 Plus selected in IB but run the simulator on iPhone 7 causing the board to go off the screen. If I select iPhone 7 in both IB and the simulator, it works fine.

I have been having difficulty finding an answer for this problem. Any help would be appreciated.

Board too big on iPhone 7

Because Storyboard set to iPhone 7 Plus

The app first draws the spaces in the init(coder):

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    let spaces: CGFloat = CGFloat(Constants.numberOfSpaces)

    spaceMargin = 16
    spaceWidth = (bounds.width - (spaces - 1) * spaceMargin) / spaces
    spaceHeight = spaceWidth
    pawnTop = bounds.height * (-3/304)
    pawnMargin = bounds.width * (1/304)
    pawnHeight = bounds.height * (48/304)
    pawnWidth = bounds.width * (44/304)

    pawnDict = [:]
    spaceDict = [:]

    for column in 0..<Constants.numberOfSpaces {
        for row in 0..<Constants.numberOfSpaces {
            let coordinate = try! Coordinate(column: column, row: row)
            drawSpace(at: coordinate)
        }
    }
}

Then this is called by my controller:

func updateBoard() {

    guard let board = dataSource?.currentBoard() else {
        return
    }

    // Remove previous pawns
    for subview in subviews {
        if let pawnView = subview as? PawnView {
            pawnView.removeFromSuperview()
        }
    }

    pawnDict = [:]

    // Draw new pawns based on placement in board model
    for column in 0..<Constants.numberOfSpaces {
        for row in 0..<Constants.numberOfSpaces {
            let coordinate = try! Coordinate(column: column, row: row)
            let space = board.getSpace(coordinate)
            if space.hasPawn {
                drawPawn(at: coordinate)
            }
        }
    }
}

Solution

  • I think your problem is due to the fact that a UIView doesn't know it's bounds in init. Take a look at the view lifecycle here. To solve your problem you have two options: use auto layout to draw your board - OR - wait until later in the view lifecycle draw it.

    More info here