Hiren Gujarati
Hiren Gujarati

Reputation: 1049

Mac-catalyst - minimum window size for Mac catalyst app

Mac catalyst allows to resize window, is there any way to provide minimum window size for Mac catalyst app?

Upvotes: 32

Views: 9261

Answers (8)

marcelosalloum
marcelosalloum

Reputation: 3531

Just add the following chunk of code to your application:didFinishLaunchingWithOptions method (for UIKit projects) or to scene(_:willConnectTo:options:) (for SwiftUI projects):

UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }.forEach { windowScene in
    windowScene.sizeRestrictions?.minimumSize = CGSize(width: 480, height: 640)
}

PS: you can also set the maximumSize property there

PS2: If you set both minimumSize and maximumSize to the same value, the window size will remain static and won't be resizable.

Upvotes: 27

COzkurt
COzkurt

Reputation: 427

Inside your scene delegate you can do following :

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
    // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
    // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
    guard let scene = (scene as? UIWindowScene) else { return }

    #if targetEnvironment(macCatalyst)
        scene.sizeRestrictions?.minimumSize = CGSize(width: 800, height: 1100)
        scene.sizeRestrictions?.maximumSize = CGSize(width: 1280, height: 1200)
    #endif
}

Upvotes: 9

Andy G
Andy G

Reputation: 129

I made a small research. So I made the following addition to my SceneDelegate's func scene:

  func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        if UIDevice.current.systemName.contains("Mac") {
            window?.windowScene?.sizeRestrictions?.minimumSize = CGSize(width: 1024, height: 768)
        } else {
           // iOS - nothing to change
        }

I'm not sure that if system name clause is required as the window.windowScene.sizeRestrictoins is nil for iOS, but added this for clear understanding and possible future updates.

I choose 1024x768 as the smallest iPad landscape size (Catalyst reports device as iPad with Mac OS in landscape mode)

Upvotes: 0

Marius Kažemėkaitis
Marius Kažemėkaitis

Reputation: 1973

Use sizeRestrictions?.minimumSize or sizeRestrictions?.maximumSize to set minimum or maximum size for your Mac app window.

Open your SceneDelegate and:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
   guard let scene = (scene as? UIWindowScene) else { return }

   scene.sizeRestrictions?.minimumSize = CGSize(width: 800, height: 600)
   scene.sizeRestrictions?.maximumSize = CGSize(width: 800, height: 600)
}

Upvotes: 3

adamfootdev
adamfootdev

Reputation: 1195

Just add this to your Scene Delegate:

window?.windowScene?.sizeRestrictions?.minimumSize = CGSize(width: 900.0, height: 750.0)

I also added how to set the maximum size as the greatest possible value:

window?.windowScene?.sizeRestrictions?.maximumSize = CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)

Upvotes: 2

William Denniss
William Denniss

Reputation: 16336

Objective-C version of @marcelosalloum's answer:

for (UIScene* scene in UIApplication.sharedApplication.connectedScenes) {
    if ([scene isKindOfClass:[UIWindowScene class]]) {
        UIWindowScene* windowScene = (UIWindowScene*) scene;
        windowScene.sizeRestrictions.minimumSize = CGSizeMake(480, 640);
    }
}

Upvotes: 4

James T Snell
James T Snell

Reputation: 1678

Here's an expanded version of @marcelosalloum's excellent answer..

Step 1. Open AppDelegate.swift

Step 2. Locate func application(), insert your version of @marcelosalloum's code here (or make a call to a function your create for this, as I did).

Step 3. Optionally assert that your code only run on platforms with the suitable Swift API's (use #available)


Example Code (In AppDelegate.swift)

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    addWindowSizeHandlerForMacOS()

    return true
}

func addWindowSizeHandlerForMacOS() {
    if #available(iOS 13.0, *) {
        UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }.forEach { windowScene in
            windowScene.sizeRestrictions?.minimumSize = CGSize(width: 800, height: 1100)
            windowScene.sizeRestrictions?.maximumSize = CGSize(width: 800, height: 1100)
        }
    }
}

Example Screenshot

In my app, I defined a function named addWindowSizeHandlerForMacOS() starting on line 23. Then I called it from application() in AppDelegate.swift (line 18).

Xcode Screenshot

Upvotes: 15

Nikolay Tabunchenko
Nikolay Tabunchenko

Reputation: 929

Implement Objective-C class with this method:

 - (void)setMinimumSize:(CGSize)size {
     id app = NSClassFromString(@"NSApplication");
     id shared = [app valueForKeyPath:@"sharedApplication"];
     id mainWindow = [shared valueForKeyPath:@"mainWindow"];

     NSValue *nssize = [NSValue valueWithCGSize:size];
     [mainWindow setValue:nssize forKeyPath:@"minSize"];
 }

To call from Swift - use bridging header.

Upvotes: 5

Related Questions