Maccatalyst App: How to Close a Window Without Terminating The App

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



Leave a reply



Submit