adds
adds

Reputation: 1

How do I override a size class?

I have a view controller. Basically, I want check some conditions, and if those conditions are true, I want to set it's size class manually (override it's default size class).

To do so, I would have to override it's UITraitCollection. I did some research, and was able to find this function:

setOverrideTraitCollection(collection: UITraitCollection!, forChildViewController childViewController: UIViewController!)

The function allows me to override the trait collection of a child view controller, but I want the view controller to be able to override it's own traits.

So just to recap, I want to do the following. When a view controller loads, I want it to check some conditions. If they are true, I want the view controller to override it's size class to a custom one.

Thanks for the help!

Upvotes: 0

Views: 3053

Answers (4)

Ely
Ely

Reputation: 9141

When using iOS 17 or newer, you can override trait properties of the view controller by using the traitOverrides property. Example:

override func viewDidLoad() {
    super.viewDidLoad()
    
    traitOverrides.horizontalSizeClass = .compact
}

Upvotes: 0

Hlung
Hlung

Reputation: 14338

You can use a wrapper view controller. Implement 'setOverrideTraitCollection(collection: UITraitCollection!, forChildViewController childViewController: UIViewController!)' in it, and refactor your main view controller down as a child of that wrapper.

Upvotes: 1

trapper
trapper

Reputation: 12003

I just override UIViewController traitCollection method, works well!

// This is so we can get 'Regular' size class layout on an iPhone in landscape
- (UITraitCollection *)traitCollection
{
    UITraitCollection *traitCollection = super.traitCollection;
    UIDevice *device = [UIDevice currentDevice];

    if (device.userInterfaceIdiom == UIUserInterfaceIdiomPhone && (device.orientation == UIDeviceOrientationLandscapeLeft || device.orientation == UIDeviceOrientationLandscapeRight)) {
        if (traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact) {
            UITraitCollection *regularCollection = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassRegular];
            traitCollection = [UITraitCollection traitCollectionWithTraitsFromCollections:@[traitCollection, regularCollection]];
        }
    }

    return traitCollection;
}

Upvotes: 1

Bogdan Laukhin
Bogdan Laukhin

Reputation: 1454

This is the way it worked for me (I was searching for the same solution for iPad to differentiate portrait/landscape modes without using of childViewController):

  1. I use separate class as subclass of UIViewController

the TraitCollectionOverrideViewController.h file:

#import <UIKit/UIKit.h>
@interface TraitCollectionOverrideViewController : UIViewController
@end

the TraitCollectionOverrideViewController.m file has only getter method for traitCollection property:

- (UITraitCollection *)traitCollection {
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
        return super.traitCollection;
    } else {
        UITraitCollection *traitCollection_hCompact = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassCompact];
        UITraitCollection *traitCollection_vRegular = [UITraitCollection traitCollectionWithVerticalSizeClass:UIUserInterfaceSizeClassRegular];
        UITraitCollection *traitCollection_CompactRegular = [UITraitCollection traitCollectionWithTraitsFromCollections:@[traitCollection_hCompact, traitCollection_vRegular]];

        UITraitCollection *traitCollection_hRegular = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassRegular];
        UITraitCollection *traitCollection_RegularRegular = [UITraitCollection traitCollectionWithTraitsFromCollections:@[traitCollection_hRegular, traitCollection_vRegular]];

        BOOL willTransitionToPortrait = self.view.frame.size.height > self.view.frame.size.width;

        UITraitCollection *traitCollectionForOverride = willTransitionToPortrait ? traitCollection_CompactRegular : traitCollection_RegularRegular;
        return traitCollectionForOverride;
    } 
}

I customised it in the way to use Custom/Regular size class for iPad portrait mode and standard Regular/Regular size class for iPad landscape mode

  1. Then in my real view controller class I use just subclassing from this custom class: @interface ForecastViewController : TraitCollectionOverrideViewController

  2. And then last part you need to do - set up constrains in the storyboard related to size class you need.

Upvotes: -1

Related Questions