3

I am trying to programmatically close a view controller in my Cocoa App. Is this possible? I saw a post about it in Objective-C, but I haven't been able to find one that works in Swift. I've tried this code inside a function, and then calling the function.self.dismissViewController(self) However it gives me SIGABRT. I don't want the user to have to press a button or do anything, but just have the back controller to close once I "show" the next View Controller (I have a self pressing IBOutlet button that is automatically sending the view to the next page, but doesn't seem to be able to close the current page). Is there a working code for closing the Parent View Controller?

  • See if [this Q&A](http://stackoverflow.com/questions/12509422/how-to-perform-unwind-segue-programmatically) can help you out (See smileBot:s answer for Swift). – dfrib Jun 30 '16 at 14:58
  • How are you presenting this new view controller? – Andrea Jun 30 '16 at 14:59
  • Thanks dfri! However, they seem to be using an "exit" button at the top of view controllers that doesn't seem to exist in Xcode 7? – cheesydoritosandkale Jun 30 '16 at 15:02
  • In [this answer](http://stackoverflow.com/a/35314768/4573247) I show (with a gif animation) just how to use that "Exit" buttom, and it is based on XCode 7(.3). See if that can help you out; can you find the button? – dfrib Jun 30 '16 at 15:07
  • Wow, really great and detailed answer dfri. Would it work the same for OS X - I see that was for iOS specifically. – cheesydoritosandkale Jun 30 '16 at 15:11
  • Andrea, I am presenting it through show. The current is a NSViewController and so is the second one. – cheesydoritosandkale Jun 30 '16 at 15:12
  • My bad, I totally missed that this was OS X and not iOS. I haven't worked with OS X apps myself, so I can't say if it's the same, sorry. – dfrib Jun 30 '16 at 15:17
  • 1
    That's okay. They can be quite different I have learned the hard way in trying to work with OSX. hehe Thank you for the help though! – cheesydoritosandkale Jun 30 '16 at 15:18

4 Answers4

5

So I figured out how to get this to work - thanks everyone for the suggestions. Here is what worked for me - I connected the button from the storyboard as both a Outlet (to click itself) and a function (to close itself) and I put the Opacity of the button to 0 so it isn't visible. I had to put it specifically like and add an NSTimer to click it like this because I needed it to programmatically open another view controller before it closes. Hope this helps someone in the future!

 class Begin: NSViewController {
   @IBOutlet var close: NSButton!

override func viewWillAppear() {

     NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: #selector(click), userInfo: nil, repeats: true)
 }

func click() {
    close.performClick(nil)
}


override func viewDidLoad() {
    super.viewDidLoad()
}

@IBAction func close(sender: AnyObject) {
    self.view.window?.close()
}
} 
  • 1
    Although its more of a hack fix but it does work. You may wanna change repeats: false from true otherwise it keeps trying to close the window. – Renegade Feb 27 '18 at 17:00
0

if its a model vc the you can try [self dismissViewControllerAnimated:YES completion:nil]; or you can open another vc [self dismissViewControllerAnimated:YES completion:nil];

0

As you state it here, you may be using a navigationController, ¿am I right?. If so, you can try navigationController.popViewControllerAnimated(animated: Bool)

Hope this can help you out, kind regards.

Bruno Garelli
  • 184
  • 1
  • 7
  • Thanks Bruno! It is an NSViewController - is there a specific code I could use for that? – cheesydoritosandkale Jun 30 '16 at 15:06
  • I think you can directly call removeFromParentViewController on your view controller, let me know if this is correct – Bruno Garelli Jun 30 '16 at 15:35
  • I can use that code, but it doesn't close the parent view controller. – cheesydoritosandkale Jun 30 '16 at 15:48
  • Does it automatically become a parent controller if it is presenting another view controller as "Show"? – cheesydoritosandkale Jun 30 '16 at 15:56
  • Sorry, I hadn't understood you wanted to pop the parent. One way to do it is to directly remove it from the navigationController's stack. Try this code: **navigationController!.viewControllers.removeAtIndex( (navigationController?.viewControllers.count)! - 2)** I explain you a little bit, you remove the "count - 2" item because in fact you're taking out an item from an array, so the last item subscript is "count - 1", hence, if you want to remove the previous item you increase the subtraction number. Hope it's clear enough, I wait on your feedback – Bruno Garelli Jun 30 '16 at 15:58
  • Hi Bruno! I really appreciate you trying to help. I tried the code, but it doesn't seem to activate? Where should I put it exactly? I am also mostly working with NSViewControllers. Is this code for iOS or OS X? – cheesydoritosandkale Jun 30 '16 at 16:03
  • I know it works for sure in iOS, but should test it in OS X, after I come back from lunch I'll try it, maybe there's a small difference to be done in order for this to work. You can call it when your "next" view controller is loaded, the main idea is to remove the previous controller, so if you go back in the hierarchy you're going to see the "parent of your parent" controller, as it was removed from the stack. **This post could be useful**: https://stackoverflow.com/questions/10281545/removing-viewcontrollers-from-navigation-stack – Bruno Garelli Jun 30 '16 at 16:21
0

It is due to the NSWindow getting automatically released when you send it a close message. NSWindow has a property releasedWhenClosed that is default YES. Set it to NO, and the window does NOT get released on close, and you do not get a crash. What I do is implement a delegate that gets called when the user clicks a button (it's a borderless window), the delegate sends the window a close message. But, I find even a viewcontroller that presents a view in that window can safely issue a close with [self.view.window close]; if theWindow.releasedWhenClosed is NO. Some code from my project:

@property (nonatomic,strong) AuController *auViewController;
@property (nonatomic,strong) NSWindow *auWindow;

- (void)mustCloseWindow_auViewControllerDelegate
{
    [self.auWindow close];
    self.auWindow = nil;
}

The view does:

self.auWindow = [[NSWindow alloc] initWithContentRect:Prefs.screenRectOriginalOrigin styleMask:(NSWindowStyleMaskBorderless) backing:NSBackingStoreBuffered defer:NO];

    self.auWindow.releasedWhenClosed = NO;

    self.auViewController = [[AuViewController alloc] initWithNibName:@"AuViewController.nib" bundle:nil];
    self.auViewController.delegate = self;  // e.g. to get the close action
    [self addSubview:self.auViewController.view];
    
    self.auWindow.contentView = self.auViewController.view;
RickJansen
  • 1,526
  • 15
  • 24