How to Check If Optional Is Not Nil and Property Is True in One Expression

How to check if Optional is not nil and property is true in one expression?

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
}

Swift: Testing optionals for nil

In Xcode Beta 5, they no longer let you do:

var xyz : NSString?

if xyz {
// Do something using `xyz`.
}

This produces an error:

does not conform to protocol 'BooleanType.Protocol'

You have to use one of these forms:

if xyz != nil {
// Do something using `xyz`.
}

if let xy = xyz {
// Do something using `xy`.
}

Checking the value of an Optional Bool

With optional booleans it's needed to make the check explicit:

if boolean == true {
...
}

Otherwise you can unwrap the optional:

if boolean! {
...
}

But that generates a runtime exception if boolean is nil - to prevent that:

if boolean != nil && boolean! {
...
}

Before beta 5 it was possible, but it has been changed as reported in the release notes:

Optionals no longer implicitly evaluate to true when they have a value and false when they do not, to avoid confusion when working with optional Bool values. Instead, make an explicit check against nil with the == or != operators to find out if an optional contains a value.

Addendum: as suggested by @MartinR, a more compact variation to the 3rd option is using the coalescing operator:

if boolean ?? false {
// this code runs only if boolean == true
}

which means: if boolean is not nil, the expression evaluates to the boolean value (i.e. using the unwrapped boolean value), otherwise the expression evaluates to false

I am getting a warning comparing my OPTIONAL value to not-nil will always return true

Just remove the entry != nil clause and it will work as you require. The if let statement that proceeds it performs the not-nil check already.

guard let entry = entryForEdit else {
return
}

Java Optional if object is not null - returns the method result, if null - returns default value

A few forms:

long lastPollTime = Optional.ofNullable(object).map(o -> o.getTime()).orElse(0L);

long lastPollTime = Optional.ofNullable(object).map(YouObjectClass::getTime).orElse(0L);

long lastPollTime = Optional.ofNullable(object).isPresent() ? object.getTime() : 0;

long lastPollTime = object != null ? object.getTime() : 0;

Of these, the last one, which doesn't use Optional (and therefore doesn't strictly answer your question!) is simpler to read and has fewer runtime overheads, and so should be preferred.

Arguably, it's even simpler if you reverse the options:

long lastPollTime = object == null ? 0 : object.getTime();

... although you might prefer to have the default last -- it's a matter of personal taste.


If you really can't use ternary operators, and you're doing this a lot, you could write your own utility method:

public <T,U> U mapWithFallback(T obj, Function<T,U> function, U fallback) {
if(obj == null) {
return fallback;
} else {
return function.apply(obj);
}
}

... callable as:

long lastPollTime = mapWithFallback(object, o -> o.getTime(), 0);

... or make a complete mockery of your no-ternaries check using:

public <T,U> U ifElse( Supplier<Boolean> a, Supplier<U> ifTrue, Supplier<U> ifFalse) {
if(a.get()) {
return ifTrue.get();
} else {
return ifFalse.get();
}
}

long lastPollTime = ifElse( () -> object == null, () -> object.getTime(), () -> 0);

It's in even better taste to avoid null references altogether, so that this kind of check isn't needed -- for example using the Null Object pattern.

... or by writing methods that return Optional rather than potential nulls. Optional is a great class; use it. Just don't convert something to Optional purely so you can immediately check whether it's empty.

What's the difference between if nil != optional … and if let _ = optional …

After optimization, the two approaches are probably the same.

For example, in this case, compiling both the following with swiftc -O -emit-assembly if_let.swift:

import Darwin

// using arc4random ensures -O doesn’t just
// ignore your if statement completely
let i: Int? = arc4random()%2 == 0 ? 2 : nil

if i != nil {
println("set!")
}

vs

import Darwin

let i: Int? = arc4random()%2 == 0 ? 2 : nil

if let _ = i {
println("set!")
}

produces identical assembly code:

    ; call to arc4random
callq _arc4random
; check if LSB == 1
testb $1, %al
; if it is, skip the println
je LBB0_1
movq $0, __Tv6if_let1iGSqSi_(%rip)
movb $1, __Tv6if_let1iGSqSi_+8(%rip)
jmp LBB0_3
LBB0_1:
movq $2, __Tv6if_let1iGSqSi_(%rip)
movb $0, __Tv6if_let1iGSqSi_+8(%rip)
leaq L___unnamed_1(%rip), %rax ; address of "set!" literal
movq %rax, -40(%rbp)
movq $4, -32(%rbp)
movq $0, -24(%rbp)
movq __TMdSS@GOTPCREL(%rip), %rsi
addq $8, %rsi
leaq -40(%rbp), %rdi
; call println
callq __TFSs7printlnU__FQ_T_
LBB0_3:
xorl %eax, %eax
addq $32, %rsp
popq %rbx
popq %r14
popq %rbp
retq

Perform assignment only if right side is not nil

A single expression with the same effect as your code is

funcThatReturnsOptional().map { object.nonOptionalProperty = $0 }

but your code is definitely better readable.

Here the map() method of Optional is used and the closure is
executed only if the function does not return nil.

How to check object is nil or not in swift?

If abc is an optional, then the usual way to do this would be to attempt to unwrap it in an if statement:

if let variableName = abc { // If casting, use, eg, if let var = abc as? NSString
// variableName will be abc, unwrapped
} else {
// abc is nil
}

However, to answer your actual question, your problem is that you're typing the variable such that it can never be optional.

Remember that in Swift, nil is a value which can only apply to optionals.

Since you've declared your variable as:

var abc: NSString ...

it is not optional, and cannot be nil.

Try declaring it as:

var abc: NSString? ...

or alternatively letting the compiler infer the type.



Related Topics



Leave a reply



Submit