Closing window in swift - macos

I have a collection view and each item opens a new window with a slideshow.
The segue kind is "show" and it's opened with:
performSegue(withIdentifier: "showGalleryPlayer", sender: self)
My idea is when double click another item the window with the previous slideshow close and the new one opens. I don't know how to do it or if it is the right approach. I want only one window with the slideshow at a time.
Thanks.

When performing a segue, the following method will be invoked:
func prepare(for segue: NSStoryboardSegue, sender: Any?)
Just override this method in whichever class you perform the segue and use the provided NSStoryboardSegue object to retrieve a reference to the newly opened window (after matching the segue's identifier of course). Store the reference to the window and use it to close the window before opening the next one.

Related

How do I set the initial first responder per view in a cocoa app that switches between different views?

My Cocoa App uses one ViewController. I do not use the InterfaceBuilder On app launch a view will be created and the user can do stuff. When clicking a specific button the VC (as the view's delegate) receives a message and then replaces the view with another.
In this new view I want a specific UI element to be the first responder. So far I have not been successful.
The new view has a reference to the desired element (a subview), so the VC can pass it to the window's makeFirstResponder(:_) method.
I tried to do that in the following places:
at the end of the view's init
in the view controller's viewWillAppear()
in the VCs viewDidAppear()
in the latter two I tried:
if let myView = self.view as? MyView {
... here I try to set the UI element as firstResponder ...
}
But in any case I get the following Message:
[General] ERROR: Setting <NSTableView: 0x7f8c1f840600> as the first responder for window <NSWindow: 0x7f8c1ef0efc0>, but it is in a different window ((null))! This would eventually crash when the view is freed. The first responder will be set to nil.
So it appears that at the time I try to set the firstResponder the new view has not yet been attached to the window.
What I also tried is to override the MyView's becomeFirstResponder()method, assuming that when the view is finally presented in the window it will receive that command, but unfortunately this method does not get called.
Is there an easy way to specify an entry point for the responder chain / key view loop per view?

Need help to write different if statement

(I am) new in the Xcode.
I am making this app, and first I had 3 viewcontrollers; each used to talk with each other with a button: from the first you click a button that goes to the second, and go on. The thing is: I put some switchs in the first viewcontroller and they execute a segue for the second viewcontroller, changing a label. The first viewcontroller has 2 buttons - one of them is part of the segue of the switchs, and the other is for the third viewcontroller. Now my problem: when I click the second button on the first viewcontroller it works just fine, but if click the swicth but not the button of the segue, instead the second button the app crashes.
this is the line of my segue:
if switch1?.isOn == true
{
let secondController = segue.destination as! SecondViewController
secondController.myString1 = "blabla"; ()
As I said: it doesn't interfere in the normal use of the app, but if I click the switch, but not click the button for the segue, instead click the button for the third viewcontroller, the app crashes.
Could not cast value of type 'app2.ViewController' (0x103879548) to 'app2.SecondViewController' (0x1038793a0).
2020-02-25 20:43:39.507421+0000 app2[18433:249963] Could not cast value of type 'app2.ViewController' (0x103879548) to 'app2.SecondViewController' (0x1038793a0).
I need a way to write a condition that if other button is click other than the one of the segue, the switchs should be off.
Any help would be highly appreciated.
This error message you're getting means that segue.destination is not of type SecondViewController and in fact it appears to be of type ViewController. More than likely what this means is you have to go into your Storyboard and more closely examine:
Your segue to see if its destination is in fact of type SecondViewController
The Custom Class part of the storyboard Identity Inspector to make sure you picked a Class and Module for the view controller in question
The above answer is all pretty much in this post, plus some more context/details

Show sheet when the main window first loads

I am trying to get a sheet to load when the main window first loads.
This sheet is so that it asks the user for a file so that they are sort of forced to open a file for use in the program when they first start.
I tried to put performSegue(withIdentifier: sender:) in viewDidLoad(), however it just loads the sheet and nothing else.
override func viewDidLoad() {
super.viewDidLoad()
performSegue(withIdentifier: NSStoryboardSegue.Identifier(rawValue: "browse"), sender: self)
}
I want the main window to load, then the sheet to slide down immediately after asking the user to open a file.
Where should I put the performSegue or is there another way I should be doing this?
#mschmidt is right, I believe; you'll need to perform the segue from viewDidAppear() or windowDidBecomeMain() or similar; the view needs to have been displayed before you can segue from it.
Note that viewDidAppear() will fire when the view is drawn, whether or not it has focus; windowDidBecomeMain() will only fire when your app becomes the frontmost app; you may be working in another app but still be able to see your app's windows on-screen, and in this state windowDidBecomeMain() may not have fired yet.
And yes, both viewDidAppear() and windowDidBecomeMain() will fire every time the view appears or the window becomes main, meaning if you minimise the app then un-minimise it, both will fire again. So you'll need some way of ensuring your segue doesn't show again each time, unless you want it to. A simple boolean flag eg segueHasShown should achieve that.

New window opens incorrectly

I want to load a new window after clicking a button. This code opens new window for about 0.01 ms and close. What I'm doing wrong?
#IBAction func goToSettings(sender: AnyObject) {
let s = SettingsViewController(windowNibName: "SettingsViewController")
s.showWindow(sender)
}
The button is located in popover at menu bar.
The controller is stored in a local variable. After your goToSettings() method exits, there's no strong reference to it anymore. So, it's released and it releases the window that it owns.
You need to store a strong reference to it in some longer-lived variable, such as an instance variable of whatever class has that goToSettings() method.

How to enable undo menu item when a sheet is presented

I am creating a document based core data OSX app using storyboards. Undo and redo works fine until I present a View Controller in a sheet with a segue. Once the sheet is presented, the undo / redo buttons are grayed out.
While searching for a possible solution, I came across this article in which they say that I have to supply an undo manager to my window using the
"windowWillReturnUndoManager:" delegate method. So I implemented this method in the sourceController of my segue, and set that controller as the delegate for the window of the destinationController in the prepareForSegue method like this:
override func prepareForSegue(segue: NSStoryboardSegue, sender: AnyObject?) {
super.prepareForSegue(segue, sender: sender)
(segue.destinationController as NSViewController).view.window?.delegate = self
}
func windowWillReturnUndoManager(window: NSWindow) -> NSUndoManager? {
println(undoManager)
return undoManager
}
But the undo and redo buttons are still grayed out when I open the sheet. Note that when change the segue style to popover, the undo/redo are working perfectly. How can I resolve this?
I had the same problem and am posting here in case it might help someone. My solution was to obtain the undo manager for the window to which the sheet view controller is attached:
let undoManager = self.view.window?.firstResponder?.undoManager
self in this context is the view controller for the sheet and not the parent view controller for the sheet. Therefore, the assignment would take place within the view controller for the sheet.

Resources