Using string for comparison in "if" statement not working (SWIFT) - swift

So I am in the process of developing this app for Mac and I am using Swift. I am just learning + developing the app side by side. I have the main viewController and when you press (+) button, it opens another viewcontroller with textfield. Now i have two buttons, one says "Done" and the other says "Cancel". If you press Cancel the viewController dismisses. However, if you press "Done" then whatever you added in that textfield appears in the first ViewController.
I want to run an if statement on "Done" button. So if you haven't written anything in the textfield and you press done, it gives you an error, and if you have written something, then it allows you to press Done and it dismisses!
I created an IBOutlet for the textfield:
#IBOutlet var weblinklabel: NSTextField!
Then whatever is stored in the weblinklabel is stored in another variable:
weblinklabel.stringValue = done!
Obviously, "done" is an optional string variable, assigned as this:
var done: String? = ""
Now in my understanding, "done" variable if empty should give the error which in this case is a label that shows itself(which is isHidden = false' in viewdidload()) function initially.
This is the "if-statement" that I am trying to use:
if done != nil {
self.view.window?.close()
} else {
label1.isHidden = false
}
I believe the placement of this code isn't right. I am placing it under IBAction of the "Done" button.
Any help in this regard, will be appreciated! thanks

The easiest way to do it would be to use a method similar to what I've explained in another response here.
Basically you would check in controlTextDidChange(notification:) if the content of the text field is "right" and if it's not you disable the Done button. Conversely you enable it if the text field validates, obviously.

Related

How to make IBAction do nothing until button pressed?

I am making a swift program that rolls die when a button is tapped but before that it asks them if they believe they will roll snake eyes, yes or no.
I want to know if its possible that when yes or no is tapped it will wait for the user to tap the roll button and then execute a response based on that? I am confused on how to add an IBAction pressed.
I have tried to add the yes button IBAction into the roll button IBAction and have ended up with many errors.
#IBAction func yesButton(_ sender: Any) {
if(diceImageView1.image == diceImageView2.image){
resultText()
} else {
lossText()
//functions changes label to message telling user if they rolled snake eyes or not
}
}
I expect the user to be able to tap a response and then have to tap the roll button for the label to change.
Present a UIAlertViewController. Then do logic depending on the button.
See guide
https://medium.com/ios-os-x-development/how-to-use-uialertcontroller-in-swift-70143d7fbede

Need to use a NSTextView (or NSTextField) for a clickable URL

I'm given an arbitrary NSAttributedString (parsed from markdown, not that it matters here) which may contain URLs that I want to be clickable in a text field within an NSTableView cell. The requirements state that if the user clicks the URL, they be taken to it with the default browser. IF they click anywhere else in the cell, we have default behavior (displaying an additional info popup).
I'm attempting to use a NSTextView to display the content. However, clicking outside the URL but within the view selects the text and eats the mouse click. Making the view not selectable won't allow clicking the URL either. I also don't really want the text to be selectable but that's a minor side problem.
So... I decided to make my view controller an NSTextViewDelegate so I could use some of those callbacks. But my app crashes if I set the NSTextView's delegate property to 'self'. This happens even if I don't implement any of the functions, even though they are all optional.
I'm using Swift 3 and wonder if there's some bug or other issue there? The call stack appears to be sending a textView:willChangeSelectionFromCharacterRanges:toCharacterRanges: message even though it's not implemented. And incidentally, implementing that method isn't helping either.
Any help, or sample code in Swift 3 using the delegate protocol, would be greatly appreciated.
Here's the crash I get by simply setting the delegate property on NSTextView:
By request, here's the code that set's the delegate. Currently I just set it whenever the message changes. This can obviously be optimized but for now I just want to see it work.
var notification: SSNotification! {
didSet {
guard let notificationCellView = self.view as? SSNotificationCellView else { return }
notificationCellView.subjectLabel.stringValue = notification.subject
if let description = notification.message , description != "" {
let attrString = TSMarkdownParser.standard().attributedString(fromMarkdown: description)
notificationCellView.messageLabel.textStorage?.setAttributedString(attrString)
notificationCellView.messageLabel.isHidden = false
notificationCellView.messageLabel.delegate = self
} else {
notificationCellView.messageLabel.isHidden = true
}
}
}
I never did figure out why I was crashing but I was able to come up with a workaround. I was originally trying to make the view controller for the table cell which contained NSTextView be the delegate. I changed it so that the cell's view subclass itself was the delegate and all is well.
I don't get it but it works, so that's what matters.

Xcode 7.2.1 Making a Reset Button using a Button with Swift

I am trying to make a reset button for my app that will reset the UI to the original state. I have made a UIButton and linked it to the ViewController, but I have no idea where to go from here. I tried using the following code:
#IBAction func resetToOriginalState(sender: UIButton) {
self.resetToOriginalState (sender: UIButton)
}
It gave me the following error:
Editor placeholder in source file
Sorry if there may be an obvious answer, but I am very new to Swift and Xcode.
Is there any other way to create a reset button?
The error:
Editor placeholder in source file
Is because you are calling a function with the UIButton Class name instead of the actual button.
#IBAction func resetToOriginalState(sender: UIButton {
// this line is wrong, you shouldn't have UIButton in here
self.resetToOriginalState (sender: UIButton)
// the line should read
self.resetToOriginalState (sender: sender)
}
This way, you are passing the actual button into the function that was passed to resetToOriginalState
Seems you have too IBAction for the same button, check how many time you have #IBAction func resetToOriginalState(sender: UIButton) in your code and remove the references from the references Interface list to clean it, should there be only one :
It depends what is in the scene and what do you need to reload. As far is I know you can't really segue a ViewController to itself, but here are few options:
Try to add loadView() when the button is pressed
Duplicate the view controller, and segue between the two. (might be risky and create more work)
Reset your variables to their initial state when the button is pressed
You should give us more detail because this is implementation specific.
Nevertheless, it's not very clean, but depending on the architecture of your code, you might be able to generate a new instance of your view controller, destroy the current one, and present the new one.

Change key to true then show view in swift

OK, so I've added a view onto my Application that asks the user to accept or decline the Terms of Service. I have it so when they click accept, it changes the key "TermsAccepted" to true. If they close the app, and re-open it, it gives them access. However I'd like to be able to give them access without re-opening the app first.
So in my ViewController (Main Screen), in my viewDidLoad I have the following:
if NSUserDefaults.standardUserDefaults().boolForKey("TermsAccepted") {
// They've been accepted, do nothing.
} else {
let termsView = self.storyboard?.instantiateViewControllerWithIdentifier("FirstLaunchTerms") as! FirstLaunchTermsView
self.presentViewController(termsView, animated: true, completion: null
}
In the 'LaunchTermsView' I have the following code for when they accept the terms.
#IBAction func acceptTerms(sender : AnyObject)
{
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "TermsAccepted")
}
And thi works fine, but they have to re-open the application.
I tried to just have it so the button opens the Main View at the same time as those terms are accepted (After the key is updated) but it gives me the following error.
fatal error: unexpectedly found nil while unwrapping an Optional value (lldb)
I assumed this meant that it was wanting to re-open the launch terms view again, so I tried to move all the code from viewDidLoad to viewWillAppear so it checks each time, but it just gives the same error. (it was a long shot try before I posted on here).
I had a look at some posts on here, but a lot of them were in ObjC or just didn't give me a solution or any form of help to trying to find one myself.
As you're presenting your terms view controller you should simply be able to dismiss it when you're done with it. You don't show any other code so I'm assuming that your 'home' view controller is waiting to be revealed underneath (you don't need to try to show it again).

Use NSPanel for user input. Not opening up again

I want to display a 'NSPanel' for the user to input a name for a new folder. Why a NSPanel? Because it looks awesome! It hosts one TextField and one PushButton to confirm the name. It shall also close the window when clicked.
It displays when the "add" button gets clicked in my menu. It also closes when the "done" button gets clicked in the NSPanel. But when I click "add" again it doesn't show up anymore. That also occurs when I close it via the normal "close button" in the title bar. So it is not explicitly related to the "done"-PushButton. I also tested implementing func windowWillClose(notification: NSNotification) which also doesn't get triggered in either cases. What could be the problem? Also, does it somehow need to be a "new" window every time? Or am I using this correctly for user input? I mean it just gets instantiated once and then "shown" and "unshown" or am I wrong?
So I did a new Cocoa-Class - Subclass of NSWindowController - and let xCode create a .xib for that also. In that .xib I "designed" the NSPanel. I ticked visible at launch without that the window wouldn't appear when the menu button gets clicked. I also hooked up an IBOutlet for the NSPanelin my Cocoa Class. My Class at the moment looks like this:
import Cocoa
class NamingHUD: NSWindowController, NSWindowDelegate {
#IBOutlet var insertNameWindow: NSPanel!
#IBOutlet weak var nameTextField: NSTextField!
override var windowNibName : String! {
return "NamingHUD"
}
override func windowDidLoad() {
super.windowDidLoad()
insertNameWindow.center()
insertNameWindow.makeKeyAndOrderFront(nil)
NSApp.activateIgnoringOtherApps(true)
}
#IBAction func userSetName(sender: NSButton) {
print("Close button clicked")
insertNameWindow.close()
}
}
In my Main Class I declared it as a variable like this:
var namingHUD:NamingHUD!
and then in override func awakeFromNib() as:
namingHUD = NamingHUD()
as well as in a click handler like:
#IBAction func addClicked(sender: NSMenuItem) {
namingHUD.showWindow(nil)
}
Now. When I click and addClicked() gets called the window shows up as expected. Fine! I enter a name and hit the "done" button and it closes the window properly. Also Fine! But when I click again, say to add another folder, the window doesn't show up anymore. I also created a Preferences Window the exact same way. But with a Window instead of a NSPanel inside. That totally works as it should.
So I clearly confused something or forget something. What could it be? I openly admit that it is the first time I am working with any kind of window outside of following a tutorial. So I clearly didn't grasp the whole concept of it. I read up about windows in Apples Developer Guide and it kinda makes sense. But... well, doesn't work at the moment. Am I "misusing" the NSPanel? Shouldn't be the case as it inherits from NSWindow or?
Did you connect the window outlet of NamingHUD to your awesome panel? Nibs are loaded lazily:
namingHUD = NamingHUD() // init the controller but doesn't load the nib
...
namingHUD.showWindow(nil) // now you are loading it for the first time
It works the first time because showWindow() loads the nib and show the window referenced by the window outlet. Your panel shows up because it's set to "Visible at launch". Your of course had no window to show.
Subsequent clicks don't load the nib file again, only order the window outlet to show up. That's why your panel did not show again. FYI: an NSPanel is a subclass of NSWindow so it has everything that NSWindow has, and then some more.