Search code examples
swift3ios-simulatorxcode8screen-rotationuitraitcollection

Xcode simulator not calling traitCollectionDidChange


I am overriding traitCollectionDidChange(_) to update my compact and regular constraints. When I test this on a device by rotating the constraints get updated correctly. When I however try to test the same code in the simulator nothing happens. I interjected print statements and I can see that on simulator rotation nothing happens. Is this a bug, or do I need to do something special for the simulator?

Thanks in advance. I am using Xcode 8.2.1 btw.

This is my code:

    private var compactConstraints: [NSLayoutConstraint] = []
    private var regularConstraints: [NSLayoutConstraint] = []
    private var sharedConstraints: [NSLayoutConstraint] = []
    ...
    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {

        super.traitCollectionDidChange(previousTraitCollection)

        if (!sharedConstraints[0].isActive) {
            // activating shared constraints
            NSLayoutConstraint.activate(sharedConstraints)
        }


        if (self.traitCollection.containsTraits(in: UITraitCollection(horizontalSizeClass: UIUserInterfaceSizeClass.compact))) {

            print("going to activate: compact")
            if regularConstraints.count > 0 && regularConstraints[0].isActive {
                NSLayoutConstraint.deactivate(regularConstraints)
            }
            // activating compact constraints
            NSLayoutConstraint.activate(compactConstraints)
        } else {
            print("going to activate: regular")
            if compactConstraints.count > 0 && compactConstraints[0].isActive {
                NSLayoutConstraint.deactivate(compactConstraints)
            }
            // activating regular constraints
            NSLayoutConstraint.activate(regularConstraints)
        }

    }

The console output is as follows:

[launch app]
`going to activate: compact`
[rotate the simulator with ⌘ arrow key]
`going to activate: compact`

Small update based on hoshy's question: I am using the simulator with iPhone devices. Specifically iPhone SE.


Solution

  • horizontalSizeClass is Compact for both orientations. verticalSizeClass is regular for portrait and Compact for landscape for iPhone SE. You can change this line

    if (traitCollection.containsTraits(in: UITraitCollection(verticalSizeClass: .compact))) {
    

    or simply

    if traitCollection.verticalSizeClass == .compact {
    

    You can also use viewWillTransitionToSize:withTransitionCoordinator: if you are looking for animation to run alongside the size change animation.

    Building an Adaptive Interface from apple developer

    If your Auto Layout constraints are insufficient to achieve the look you want, you can use the viewWillTransitionToSize:withTransitionCoordinator: method to make changes to your layout. You can also use that method to create additional animations to run alongside the size-change animations. For example, during an interface rotation, you might use the transition coordinator’s targetTransform property to to create a counter-rotation matrix for parts of your interface.