Mac catalyst allows to resize window, is there any way to provide minimum window size for Mac catalyst app?
8 回答
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.
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).
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
}
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.
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);
}
}
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)
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)
}
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)