32

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

Hiren Gujarati
  • 1,039
  • 14
  • 32

8 Answers8

26

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.

marcelosalloum
  • 3,481
  • 4
  • 39
  • 63
  • 1
    How to get the window size of the iOS App when it runs on Mac? The width, because the height corresponds to the laptop screen height. It is understood that the iOS App is not running in full screen on the Mac. – Markus Oct 06 '20 at 13:55
  • 3
    Is this still working? I tried to run this code also adding maximumSize but I'm able to resize the window at will in Mac Catalyst – r4id4 Feb 02 '21 at 21:36
  • 3
    @r4id4 I found that upon `didFinishLaunchingWithOptions` the window scenes won't be setup yet so it wouldn't work; add a delay makes it work fine – hyouuu May 15 '21 at 22:58
15

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

James T Snell
  • 1,588
  • 1
  • 15
  • 28
9

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
}
COzkurt
  • 427
  • 4
  • 4
5

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.

4

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);
    }
}
William Denniss
  • 16,089
  • 7
  • 81
  • 124
3

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)
}
Marius Kažemėkaitis
  • 1,723
  • 19
  • 22
2

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)
adamfootdev
  • 1,149
  • 10
  • 15
0

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)

Andy G
  • 129
  • 2
  • 4
  • Any idea how to do this when there is no SceneDelegate. When the app is SwiftUIApp, there is no SceneDelegate – RawMean Nov 18 '20 at 18:51