How to check if `Any(not Any?)` is nil or not in swift
Using if case
:
You can use if case Optional<Any>.none = a
to test if a
is nil
:
var b: Bool?
var a = b as Any
if case Optional<Any>.none = a {
print("nil")
} else {
print("not nil")
}
nil
b = true
a = b as Any
if case Optional<Any>.none = a {
print("nil")
} else {
print("not nil")
}
not nil
Using switch
:
You can use the pattern test with switch
as well:
var b: Bool?
var a = b as Any
switch a {
case Optional<Any>.none:
print("nil")
default:
print("not nil")
}
nil
How to check that the string is not nil in swift?
The string can't be nil. That's the point of this sort of typing in Swift.
If you want it to be possibly nil, declare it as an optional:
var date : String?
If you want to check a string is empty (don't do this, it's the sort of thing optionals were made to work around) then:
if date.isEmpty
But you really should be using optionals.
check if any property in an object is nil - Swift 3
I would strongly recommend against this. State validation is something which should happen from inside a class. From inside the class, you should know better how to check validity.
class Vehicle {
var name: String?
var model: String?
var VIN: String?
func isReadyToAdvance() -> Bool {
return name != nil && model != nil && VIN != nil
}
}
let objCar = Vehicle()
objCar.name = "Volvo"
if objCar.isReadyToAdvance() {
// Go to other screen
}
If there are subclasses with different rules for isReadyToAdvance()
they can override that method.
If isReadyToAdvance()
doesn't make sense for the base class, then add it as an extension.
extension Vehicle {
func isReadyToAdvance() -> Bool {
return name != nil && model != nil && VIN != nil
}
}
@iPeter asked for something a bit more compact when there are lots of properties.
extension Vehicle {
func isReadyToAdvance() -> Bool {
// Add all the optional properties to optionals
let optionals: [Any?] = [name, model, VIN]
if (optionals.contains{ $0 == nil }) { return false }
// Any other checks
return true
}
}
How to check if an object is nil in Swift?
When an object is of a non-optional type, it cannot be nil
, so the compiler does not let you perform a check at all.
When you use as
operator with no question mark, you tell swift that he conversion must succeed, in which case you will never see nil
as the result. If you are not sure if the conversion is going to succeed or not, use conversion to an optional type. You can combine it with an implicit nil
check like this:
if let buttonSpringAnimation = self.pop_animationForKey(animationKey) as? POPSpringAnimation {
... // This block of code will be entered only when the conversion is successful
}
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.
When should I compare an optional value to nil?
It is almost always unnecessary to check if an optional is not nil
. Pretty much the only time you need to do this is if its nil
-ness is the only thing you want to know about – you don’t care what’s in the value, just that it’s not nil
.
Under most other circumstances, there is a bit of Swift shorthand that can more safely and concisely do the task inside the if
for you.
Using the value if it isn’t nil
Instead of:
let s = "1"
let i = Int(s)
if i != nil {
print(i! + 1)
}
you can use if let
:
if let i = Int(s) {
print(i + 1)
}
You can also use var
:
if var i = Int(s) {
print(++i) // prints 2
}
but note that i
will be a local copy - any changes to i
will not affect the value inside the original optional.
You can unwrap multiple optionals within a single if let
, and later ones can depend on earlier ones:
if let url = NSURL(string: urlString),
data = NSData(contentsOfURL: url),
image = UIImage(data: data)
{
let view = UIImageView(image: image)
// etc.
}
You can also add where
clauses to the unwrapped values:
if let url = NSURL(string: urlString) where url.pathExtension == "png",
let data = NSData(contentsOfURL: url), image = UIImage(data: data)
{ etc. }
Replacing nil
with a default
Instead of:
let j: Int
if i != nil {
j = i
}
else {
j = 0
}
or:
let j = i != nil ? i! : 0
you can use the nil-coalescing operator, ??
:
// j will be the unwrapped value of i,
// or 0 if i is nil
let j = i ?? 0
Equating an optional with a non-optional
Instead of:
if i != nil && i! == 2 {
print("i is two and not nil")
}
you can check if optionals are equal to non-optional values:
if i == 2 {
print("i is two and not nil")
}
This also works with comparisons:
if i < 5 { }
nil
is always equal to other nil
s, and is less than any non-nil
value.
Be careful! There can be gotchas here:
let a: Any = "hello"
let b: Any = "goodbye"
if (a as? Double) == (b as? Double) {
print("these will be equal because both nil...")
}
Calling a method (or reading a property) on an optional
Instead of:
let j: Int
if i != nil {
j = i.successor()
}
else {
// no reasonable action to take at this point
fatalError("no idea what to do now...")
}
you can use optional chaining, ?.
:
let j = i?.successor()
Note, j
will also now be optional, to account for the fatalError
scenario. Later, you can use one of the other techniques in this answer to handle j
’s optionality, but you can often defer actually unwrapping your optionals until much later, or sometimes not at all.
As the name implies, you can chain them, so you can write:
let j = s.toInt()?.successor()?.successor()
Optional chaining also works with subscripts:
let dictOfArrays: ["nine": [0,1,2,3,4,5,6,7]]
let sevenOfNine = dictOfArrays["nine"]?[7] // returns {Some 7}
and functions:
let dictOfFuncs: [String:(Int,Int)->Int] = [
"add":(+),
"subtract":(-)
]
dictOfFuncs["add"]?(1,1) // returns {Some 2}
Assigning to a property on an optional
Instead of:
if splitViewController != nil {
splitViewController!.delegate = self
}
you can assign through an optional chain:
splitViewController?.delegate = self
Only if splitViewController
is non-nil
will the assignment happen.
Using the value if it isn’t nil
, or bailing (new in Swift 2.0)
Sometimes in a function, there’s a short bit of code you want to write to check an optional, and if it’s nil
, exit the function early, otherwise keep going.
You might write this like this:
func f(s: String) {
let i = Int(s)
if i == nil { fatalError("Input must be a number") }
print(i! + 1)
}
or to avoid the force unwrap, like this:
func f(s: String) {
if let i = Int(s) {
print(i! + 1)
}
else {
fatalErrr("Input must be a number")
}
}
but it’s much nicer to keep the error-handling code at the top by the check. This can also lead to unpleasant nesting (the "pyramid of doom").
Instead you can use guard
, which is like an if not let
:
func f(s: String) {
guard let i = Int(s)
else { fatalError("Input must be a number") }
// i will be an non-optional Int
print(i+1)
}
The else
part must exit the scope of the guarded value, e.g. a return
or fatalError
, to guarantee that the guarded value will be valid for the remainder of the scope.
guard
isn’t limited to function scope. For example the following:
var a = ["0","1","foo","2"]
while !a.isEmpty {
guard let i = Int(a.removeLast())
else { continue }
print(i+1, appendNewline: false)
}
prints 321
.
Looping over non-nil items in a sequence (new in Swift 2.0)
If you have a sequence of optionals, you can use for case let _?
to iterate over all the non-optional elements:
let a = ["0","1","foo","2"]
for case let i? in a.map({ Int($0)}) {
print(i+1, appendNewline: false)
}
prints 321
. This is using the pattern-matching syntax for an optional, which is a variable name followed by ?
.
You can also use this pattern matching in switch
statements:
func add(i: Int?, _ j: Int?) -> Int? {
switch (i,j) {
case (nil,nil), (_?,nil), (nil,_?):
return nil
case let (x?,y?):
return x + y
}
}
add(1,2) // 3
add(nil, 1) // nil
Looping until a function returns nil
Much like if let
, you can also write while let
and loop until nil
:
while let line = readLine() {
print(line)
}
You can also write while var
(similar caveats to if var
apply).
where
clauses also work here (and terminate the loop, rather than skipping):
while let line = readLine()
where !line.isEmpty {
print(line)
}
Passing an optional into a function that takes a non-optional and returns a result
Instead of:
let j: Int
if i != nil {
j = abs(i!)
}
else {
// no reasonable action to take at this point
fatalError("no idea what to do now...")
}
you can use optional’s map
operator:
let j = i.map { abs($0) }
This is very similar to optional chaining, but for when you need to pass the non-optional value into the function as an argument. As with optional chaining, the result will be optional.
This is nice when you want an optional anyway. For example, reduce1
is like reduce
, but uses the first value as the seed, returning an optional in case the array is empty. You might write it like this (using the guard
keyword from earlier):
extension Array {
func reduce1(combine: (T,T)->T)->T? {
guard let head = self.first
else { return nil }
return dropFirst(self).reduce(head, combine: combine)
}
}
[1,2,3].reduce1(+) // returns 6
But instead you could map
the .first
property, and return that:
extension Array {
func reduce1(combine: (T,T)->T)->T? {
return self.first.map {
dropFirst(self).reduce($0, combine: combine)
}
}
}
Passing an optional into a function that takes an optional and returns a result, avoiding annoying double-optionals
Sometimes, you want something similar to map
, but the function you want to call itself returns an optional. For example:
// an array of arrays
let arr = [[1,2,3],[4,5,6]]
// .first returns an optional of the first element of the array
// (optional because the array could be empty, in which case it's nil)
let fst = arr.first // fst is now [Int]?, an optional array of ints
// now, if we want to find the index of the value 2, we could use map and find
let idx = fst.map { find($0, 2) }
But now idx
is of type Int??
, a double-optional. Instead, you can use flatMap
, which “flattens” the result into a single optional:
let idx = fst.flatMap { find($0, 2) }
// idx will be of type Int?
// and not Int?? unlike if `map` was used
Check If Custom Class Not Nil --- Swift Is Converting It To A UInt8
I have a custom image class and I am just trying to check if its not nil
Be sure that iamge.uiImage
is Optional. Otherwise you can't compare it to nil
In this case Swift helps you do avoid extra validation != nil
.
On other hand if uiImage
is not Optional (a.e. marked without ?
) means that this value is not nil
and you can remove if
validation statement because it doesn't make sense
how can I check if my custom class is nil?
If you feel pretty confident that custom class is not nil
- don't check it.
If it might be nil
- define it as Optional like:
var uiImage:UIImage?
In this case each time when you are going to use it, need to unwrap it 1st
The nil check for presence of an element is not working as expected in functional test case
Try below method for nil check:
- (instancetype)assertWithMatcher:(id<GREYMatcher>)matcher error:(__strong NSError **)errorOrNil
Try below code to check nil:
let errorOrNil
EarlGrey().selectElementWithMatcher(grey_accessibilityID("TabBar-Navigation-Search")).assertWithMatcher(grey_sufficientlyVisible(), error:&errorOrNil)
if errorOrNil != nil {
TabBarNavigation().navigateToSearch()
} else {
assentViewModelsSwifts.signInCheck()
assentViewModelsSwifts.enterLoginCredentials("username", password: "password")
let visibleSignInButtonMatcher = grey_allOfMatchers(grey_accessibilityID("Login-Button-SignIn"), grey_sufficientlyVisible())
EarlGrey().selectElementWithMatcher(visibleSignInButtonMatcher).performAction(grey_tap())
TabBarNavigation().navigateToSearch()
Log.info("Landed on Search Page")
}
Related Topics
Wait Until an Asynchronous API Call Is Completed - Swift/Ios
Need to Check That Braces in Given Array Are Balanced or Not
How to Change Colour of the Certain Words in Label - Swift 3
How Is a Return Value of Anyobject! Different from Anyobject
Spritekit - Create at Random Position Without Overlapping
Get Larger Facebook Image Through Firebase Login
Not Condition in 'If Case' Statement
Subclass.Fetchrequest() Swift 3.0, Extension Not Really Helping 100%
"Ambiguous Use of 'Propertyname'" Error Given Overridden Property with Didset Observer
What Does <> (Angle Brackets) Do on Class Names in Swift
How to Set a Specific Default Time for a Date Picker in Swift
Swift Mkmapview Drop a Pin Annotation to Current Location
Find Item of Specific Type in Array
App Crash on Sign in (Xcode 9.3) Exc_Bad_Access (Code=1, Address=0X1)
How to Hide the Navigationbar When Embedding Swiftui in Uikit