Using Swift, I have an NSStatusItem
, and when I click it, I want to check if an NSWindow
is visible. If it is, hide it, if it isn't, call a function to show the NSWindow
.
My NSWindow is a class property in my app delegate, var window: NSWindow?
. In my method which responds to the clicking of the NSStatusItem
, I am trying to use Optional Chaining to do the following:
if self.window?.visible {
self.window!.orderOut(self) // or self.window?.orderOut(self), same behavior
}
else {
displayWindow()
}
However, if window
is not nil
, it goes into the if
block every time. If window
is nil
, it goes into the else
block every time. In other words, this doesn't appear to work. I cannot check if window
is not nil
and if window
is visible in one expression. (I figured this was an obvious place to use Optional Chaining.)
I tried this, just to see what would happen:
if self.window!.visible {
self.window!.orderOut(self)
}
else {
displayWindow()
}
Which works if window
is not nil
. window
is hidden at first, so it hits the else
block and shows the window. The next time the method is called, window
is visible, so it does the else
block. And so on. Exactly what I want, except I cannot check if window
is nil
. If it is nil
, I get the obvious crash "fatal error: Can't unwrap Optional.None
"
The following allows me to check if window
is nil
, and then check if it is visible:
if let win = self.window {
if win.visible {
win.orderOut(self)
} else {
displayWindow()
}
}
else {
NSLog("self.window == nil")
}
However, this is wordy and I really think I should be able to do the first way. Do I really have to do it this third way? Or am I correct in assuming the first case not working is a bug?
EDIT: this way also works:
if self.window && self.window!.visible {
self.window?.orderOut(self)
}
else {
displayWindow()
}
But again, isn't Optional Chaining meant to replace this kind of thing?
Edit:
Cezar's solution (first comment below) turned out to be much more correct:
self.window?.visible == true
There is a serious flaw with my solution below. If self.window
is nil
, it will try to unwrap nil
and crash.
--Old Answer--
As mentioned in my comment:
When you use Optional Chaining, the returned value is always an Optional. That means self.window?.visible
returns Bool?
. And since it always exists when window is not nil
, it will pass the check.
This is explained in the Swift book section on Optional Chaining. It makes sense because when you use Optional Chaining, the return value always has a chance to return nil
, and that doesn't depend on the final value in the "chain".
Note: The above is still true, but the following suggestion was terrible :[
So your desired syntax is:
(self.window?.visible)!
Here's some code for you to paste into a Playground to play with this behavior:
import Foundation
class a {
let t = true;
let f = false;
}
class b {
var A:a?
}
let B = b()
B.A = a()
if B.A?.f == true {
println("true")
}
else {
println("false") // prints False
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With