dismiss nsviewcontroller swift doesn't work - xcode

That's the button action:
#IBAction func readyPressed(sender: NSButton) {
self.dismissController(Hardness)
println(1)
self.performSegueWithIdentifier("manual", sender: self)
}
When I press the button, println works, segue works, but NSViewController "Hardness" doesn't close

Try this line to close the window: self.view.window?.close()

You must add Action from button to First Responder - dismissController:

you can try
NSViewController().dismiss(vc).
the viewcontroller to be dismissed should be passed as argument and the caller could be any NSViewController object.

Please try using
self.dismissViewControllerAnimated(true, completion: {});
or use
navigationController.popViewControllerAnimated(true)
as presented here
how to dismiss a view controller in swift

Related

performSegueWithIdentifier causes fatal error: unexpectedly found nil while unwrapping an Optional value

What I need was to detect which cell was selected on my tableView, and using the indexPath.row to get the index of my object array which is personList, and pass that data to another View Controller and print on the label.
However, I received an error fatal error: unexpectedly found nil while unwrapping an Optional value
Below are my codes.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
selectedCell = indexPath.row
performSegueWithIdentifier("DetailScreen", sender: nil)
}
override func performSegueWithIdentifier(identifier: String, sender: AnyObject?) {
//detailedView.personName = personList[selectedCell].GetPersonName()
detailedView.LastNameLabel.text = personList[selectedCell].GetLastName()
}
The problem is that you initialize the detailedView in the wrong way. Do it like this:
// IMPORTANT: Override prepareForSegue for your purpose, not performSegueWithIdentifier
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "DetailScreen" {
// Do the initialization here. You don't need a global variable.
if let detailedView = segue.destinationViewController as? PersonDetailScreen {
//detailedView.personName = personList[selectedCell].GetPersonName()
detailedView.LastNameLabel.text = personList[selectedCell].GetLastName()
}
}
}
PS: You are overriding the wrong function.
EDIT
As mentioned in your comment didSelectRowAtIndexPath and prepareForSegue doesn't coexist because the method you used for creating the segue is wrong. And with that, your code is doing more wrong than doing the right thing. Right now you might have created the segue by control dragging starting from the UITableView prototype cell to the destination view controller. Now when you do this what happens is, you are telling that the segue must be performed on the clicking on that particular cell itself, which means you are setting its action right in the storyboard. So even if you don't implement didSelectRowAtIndexPath, your code will still navigate to the second ViewController when the cell is clicked. But your requirement is that you must do some custom operations when the cell is clicked and then navigate to the second viewcontroller. For doing that, delete the current segue and then create a new segue with the same identifier like the way you create a normal segue - by control dragging from the source ViewContoller(not the tableview cell prototype) to the destination view controller. Then replace the override func performSegueWithIdentifier(identifier: String, sender: AnyObject?) function with the function I have provided in my original answer and then your code will work smooth.
PS: Make sure your Identifier is named correctly.
'NSInvalidArgumentException', reason: 'Receiver (<PersonDisplay.FirstViewController: 0x7feabaec2870>) has no segue with identifier 'DetailScreen''
This happens since you haven't set the name for the segue correctly in the storyboard. So rectify that as well. Specify the identifier for the segue in the storyboard.
You should pass valuable to detailedView and assign to label in viewDidLoad:
detailedView.lastName = personList[selectedCell].GetLastName()
Go viewDidload of detailedView:
detailedView.LastNameLabel.text = detailedView.lastName

Handle close event of the window in Swift

How to handle close event of the window using swift, for example, to ask "Are you sure you want to close the form?"
The form will be closed in the case "yes" and not closed in the case "no". Showing message box is not a problem for me.
viewWillDisappear() works for minimizing also, but I need only close event.
Thanks.
Like said above, you should make the ViewController an NSWindowDelegate, but you should handle windowWillClose, not windowShouldClose. windowShouldClose is to determine if the window is able to close or not, not an event that the window is actually closing.
I also found that you need to set up the delegate in viewDidAppear, not viewDidLoad. For me self.view.window wasn't defined yet in viewDidLoad.
override func viewDidAppear() {
self.view.window?.delegate = self
}
I was having the same query too, solved it using the method explained in detail here: Quit Cocoa App when Window Close using XCode Swift 3
It needs three steps:
Conform toNSWindowDelegate in your ViewController class
Override viewDidAppear method
Add windowShouldClose method
The added code should look like this:
class ViewController: NSViewController, NSWindowDelegate {
// ... rest of the code goes here
override func viewDidAppear() {
self.view.window?.delegate = self
}
func windowShouldClose(_ sender: Any) {
NSApplication.shared().terminate(self)
}
}
You can use the NSWindowDelegate protocol in your ViewController class. (See the documentation here)
To make your class conform to the protocol:
class ViewController: NSObject, NSWindowDelegate
To detect when the window's close button has been clicked, use windowShouldClose:
From the doc:
Tells the delegate that the user has attempted to close a window [...]
In this method, you can use NSAlert to prompt the user on whether or not they really want to close the window.
EDIT (in response to #Mr Beardsley's comment)
To make your ViewController the delegate, use:
window.delegate = self
Where self is the ViewController and window is the window you're using. You can put this in viewDidLoad:.
Just add this function to AppDelegate ...
func applicationShouldTerminateAfterLastWindowClosed (_ theApplication: NSApplication) -> Bool {
return true
}

Why in ElCapitan GM and Xcode 7 GM the popover appears outside of the view?

Does someone knows why in ElCapitan GM and Xcode 7 GM the popover appears outside of the view?
The popover is triggered by the "Button".
The picture below is a new project with no code written by me, jut a button.
Is it a bug or a new "feature"?
I just tried it, and it seems that you can't set the popover anchor in the Storyboard. Perhaps this is indeed a bug in the new release.
To display the popover programmatically, set the StoryboardID of your popover view controller, for example: "PopoverViewController". Below, it's implemented in the main view controller as a lazy var, so it's instantiated just once, the first time it's referenced.
Connect an IBAction from your button to the main view controller — here, a function called "displayPopover". The "guard let" statement makes sure the sender can be cast as an NSButton.
Then, just call:
presentViewController:asPopover...
lazy var popoverViewController: NSViewController = {
return self.storyboard!.instantiateControllerWithIdentifier("PopoverViewController")
as! NSViewController
}()
#IBAction func displayPopover(sender: AnyObject) {
guard let button = sender as? NSButton else {return}
self.presentViewController(popoverViewController, asPopoverRelativeToRect: button.frame, ofView: button, preferredEdge: NSRectEdge.MaxY, behavior: NSPopoverBehavior.Transient)
}

How to transport the Spotlight API code to the view controller

I have written my Spotlight API code and it seems to be working okay. I can check it out in the spotlight but there's only one problem :
It won't take me to the desired view controller! How do I do that? I've added a
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showIt" {
let ThatVC = segue.destinationViewController as! ItThat
}
}
but it still won't take me to the right spot. Where am I going wrong?
prepareForSegue is used to notify the view controller that a segue is about to be performed (what data to prepare, confirms destination, etc). prepareForSegue is only called when a segue has already been initiated. It does not however perform the segue itself.
If your segue is unconditional, just use a standard segue in Interface Builder (pull from the UIButton to your destination scene).
If your segue is conditional, pull from the UIButton's parent scene to the destination scene in Interface Builder. Once this is finished, you can create a new #IBAction and perform a segue manually.
#IBAction func fooAction() {
performSegueWithIdentifier("showIt", sender: self)
}
Just make sure "showIt" is the segue's identifier.

What is a StoryBoard ID and how can I use this?

I am new to IOS developing and recently started in Xcode 4.5. I saw for every viewController that i could set some identity variables including the storyboard ID. What is this, and how can I use it?
I started searching on stackoverflow and couldn't find any explanation for it.
I assumed it's not just some stupid label that I can set to remember my controller right? What does it do?
The storyboard ID is a String field that you can use to create a new ViewController based on that storyboard ViewController. An example use would be from any ViewController:
//Maybe make a button that when clicked calls this method
- (IBAction)buttonPressed:(id)sender
{
MyCustomViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"MyViewController"];
[self presentViewController:vc animated:YES completion:nil];
}
This will create a MyCustomViewController based on the storyboard ViewController you named "MyViewController" and present it above your current View Controller
And if you are in your app delegate you could use
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard"
bundle: nil];
Edit: Swift
#IBAction func buttonPressed(sender: AnyObject) {
let vc = storyboard?.instantiateViewControllerWithIdentifier("MyViewController") as MyCustomViewController
presentViewController(vc, animated: true, completion: nil)
}
Edit for Swift >= 3:
#IBAction func buttonPressed(sender: Any) {
let vc = storyboard?.instantiateViewController(withIdentifier: "MyViewController") as! ViewController
present(vc, animated: true, completion: nil)
}
and
let storyboard = UIStoryboard(name: "MainStoryboard", bundle: nil)
To add to Eric's answer and update it for Xcode 8 and Swift 3:
A storyboard ID does exactly what the name implies: it identifies. Just that it identifies a view controller in a storyboard file. It is how the storyboard knows which view controller is which.
Now, don't be confused by the name. A storyboard ID doesn't identify a 'storyboard'. A storyboard, according to Apple's documentation, 'represents the view controllers for all or part of your app’s user interface.' So, when you have something like the picture below, you have a storyboard called Main.storyboard which has two view controllers, each of which could be given a storyboard ID (their ID in the storyboard).
You can use a view controller's storyboard ID to instantiate and return that view controller. You can then go ahead to manipulate and present it however you want. To use Eric's example, say you want to present a view controller with identifier 'MyViewController' when a button is pressed, you would do it this way:
#IBAction func buttonPressed(sender: Any) {
// Here is where we create an instance of our view controller. instantiateViewController(withIdentifier:) will create an instance of the view controller every time it is called. That means you could create another instance when another button is pressed, for example.
let vc = storyboard?.instantiateViewController(withIdentifier: "MyViewController") as! ViewController
present(vc, animated: true, completion: nil)
}
Please take note of changes in syntax.

Resources