macCatalyst app: how to close a window without terminating the app?
I've discussed the problem with Apple technical developer support. After a long discussion, they accepted that this is a bug on Apple side. It's escalated to the engineering team.
UPDATE:
Apple Engineering team has provided the following information regarding this issue and it worked for me:
We were able to prevent the quitting behavior by adding NSSupportsAutomaticTermination = NO to info.plist
Using applicationShouldTerminateAfterLastWindowClosed with Mac Catalyst
The problem is this line:
NSObject *appKit = [[[bundle classNamed:@"AppKitBridge"] alloc] init];
Your appKit
object is a local variable so your AppKitBridge instance goes out of existence one line later. You need this object to persist if it is to function as the app/window delegate. Assign it to an instance property of some persistent object.
How to disable fullscreen button in macOS app (Mac Catalyst)
I found how to do it by creating a macOS bundle target and Helper class to use and include AppKit API, then disabling the zoom button on the didFinishLaunchingWithOptions method.
For anyone who faces this issue when enabling Mac Catalyst, please follow the steps on below link:
https://crunchybagel.com/disabling-the-mac-zoom-maximise-button-in-catalyst/
How do Mac Catalyst apps handle lifecycle transitions?
My scenario is typical: Mac apps made with Catalyst simply do not transition through lifecycle stages as often as they do on iOS.
From this article:
- State changes, however, do affect the Mac less, as are almost always Foreground + Active on macOS.
- Apps only enter background during termination and inactive when launching in the background.
- Your app should still take App Napp into account
How to do a Close Confirmation with a Xamarin Forms mac App?
After a lot of experimenting, I did find a solution. Here is what officially passed Apple's review. It requires that n menu action is linked as "New Window". It keeps tracks of the open windows and when there is only one left, it prompts to close the app. If the user closes all the windows and keeps the app running, they have the option to open a new window in the menu.
[Register("AppDelegate")]
public class AppDelegate : FormsApplicationDelegate
{
public NSWindow window;
private bool closeApp;
private List<NSWindow> openWindows;
public override NSWindow MainWindow
{
get { return window; }
}
public AppDelegate()
{
this.closeApp = false;
this.openWindows = new List<NSWindow>();
createNewWindow();
}
[Action("newWindow:")]
public void newWindow(NSObject sender)
{
createNewWindow();
this.window.MakeKeyAndOrderFront(sender);
LoadApplication(new App());
base.DidFinishLaunching(null);
}
private void createNewWindow()
{
var style = NSWindowStyle.Closable | NSWindowStyle.Resizable | NSWindowStyle.Titled;
var rect = new CoreGraphics.CGRect(200, 1000, 1024, 768);
window = new MainWindow(rect, style, NSBackingStore.Buffered, false);
window.Title = "MyApp"; // choose your own Title here
window.TitleVisibility = NSWindowTitleVisibility.Hidden;
window.WillClose += Window_WillClose;
openWindows.Add(window);
}
private void Window_WillClose(object sender, System.EventArgs e)
{
openWindows.Remove((NSWindow)((NSNotification)sender).Object);
if (openWindows.Count == 0)
{
var confirmation = new NSAlert()
{
AlertStyle = NSAlertStyle.Warning,
InformativeText = "Do you want to exit the app?",
MessageText = "Exit?"
};
confirmation.AddButton("Yes");
confirmation.AddButton("No");
var result = confirmation.RunModal();
if (result == 1001)
{
this.closeApp = false;
}
else
{
//terminate the app
this.closeApp = true;
}
}
}
public override bool ApplicationShouldTerminateAfterLastWindowClosed(NSApplication sender)
{
return closeApp;
}
public override void DidFinishLaunching(NSNotification notification)
{
Forms.Init();
LoadApplication(new App());
base.DidFinishLaunching(notification);
}
}
Show and hide window instead of terminating app on close click in cocoa app
I have found solution. Thanks to @Silvester suggestion to present NSViewController.
On button click event :
@IBAction func onButtonClick(_ sender: VSButton) {
let animator = ReplacePresentationAnimator()
let vc = self.storyboard?.instantiateController(withIdentifier: "identifier") as! yourVC
present(vc, animator: animator)
}
Custom animator class :
class ReplacePresentationAnimator: NSObject, NSViewControllerPresentationAnimator {
func animatePresentation(of viewController: NSViewController, from fromViewController: NSViewController) {
if let window = fromViewController.view.window {
NSAnimationContext.runAnimationGroup({ (context) -> Void in
fromViewController.view.animator().alphaValue = 0
}, completionHandler: { () -> Void in
viewController.view.alphaValue = 0
window.contentViewController = viewController
viewController.view.animator().alphaValue = 1.0
})
}
}
func animateDismissal(of viewController: NSViewController, from fromViewController: NSViewController) {
if let window = viewController.view.window {
NSAnimationContext.runAnimationGroup({ (context) -> Void in
viewController.view.animator().alphaValue = 0
}, completionHandler: { () -> Void in
fromViewController.view.alphaValue = 0
window.contentViewController = fromViewController
fromViewController.view.animator().alphaValue = 1.0
})
}
}
}
This will work perfectly with Silvester MyWindowController. Thank you.
Related Topics
Pattern Variable Binding Cannot Appear in an Expression
How to Properly Calculate 1 Second with Deltatime in Swift
How to Initialize a Unichar Variable in Swift
Swiftui Sheet Gets Dismissed the First Time It Is Presented
Hex String to Text Conversion - Swift 3
Swiftui: How to Switch to a New Navigation Stack with Navigationviews
Array Extension Called from Other Module
Swift 4.1 Deinitialize and Deallocate(Capacity:) Deprecated
Swiftui Button Interact with Map
How to Set an Initial Value for @Nsmanaged Property Pfobject Subclass
Make a Grid of Buttons of Same Width and Height in Swiftui
Formula to Pick Every Pixel in a Bitmap Without Repeating
Add a Xib File to a Swift Package
Swift-Setting a Physics Body Velocity by Angle
Uibezierpath Appending Overlapping Isn't Filled
How to Cast Up to Super Class When There Is an Override Function in the Sub Class
Xcframework Issue, a Library with the Identifier "Ios-Armv7_Arm64" Already Exists