Swift 3 Warning: Non-Optional Expression of Type 'String' Used in a Check for Optionals

Swift 3 warning: Non-optional expression of type 'String' used in a check for optionals

You are trying to unwrap a value that is already unwrapped, and hence you are getting an error because it doesn't need unwrapping again. Change your if statement to look like the following and you should be golden:

if filteredTitleList.count > indexPath.row {
let filteredTitle = filterdTitleList[indexPath.row]
}

Unfortunately there is no way to bind the variable within the if statement, hopefully they'll add one in the future.

Swift 2.x to Swift 3, Xcode complaining error : Non-optional expression of type 'String' used in a check for optionals

Don't use force unwrapping of optionals. The force unwrapping makes it a non-optional value, hence optional binding cannot be used. Moreover, array subscripting does not return an optional value, so rather than trying to use optional binding to check if the array has that many elements, after unwrapping the array, check if it has as many elements as you want to access.

if let data = data,
let responseArray = String(data: data, encoding: .utf8)?
.components(separatedBy: "|VCSPACER|"),
responseArray.count > 2 {
let result = responseArray[0]
let action = responseArray[1]
let datas = responseArray[2]
}

Non-optional expression of type 'AnyObject' used in a check for optionals

Simply remove the line that causes warning from your code and pass self as is for the JSONSerialization function. This should work without any issues:

extension Dictionary {

func toJSONString() -> String? {
if let data = try? JSONSerialization.data(withJSONObject: self, options: JSONSerialization.WritingOptions(rawValue: 0)) {
if let json = String(data: data, encoding: String.Encoding.utf8) {
return json
}
}

return nil
}
}

Non-optional expression of type uitextfield used in a check for optionals

You are forced unwrapping the value so it's a non-optional. That's what the message tells you.

Since you have definitely added the text field to the alert controller you don't need any check and the code can be shortened:

let field  = alertController.textFields![0] // or textFields.first!

No type annotation, no type casting, the compiler can infer the type.

To check for empty string there is also a more convenient syntax:

if !field.text.isEmpty { ...

Non optional expression of type NSDictionary used in a check for optionals. Error

Remove ! after NSDictionary(contentsOfFile:)

guard let fileContentArray = NSDictionary(contentsOfFile: filePath!) else {
return
}

Both guard-let-else and ! are removing optionals. There is no need to use them both for the same optional.

You could actually use the same pattern for both optionals:

guard
let filePath = filePath,
let fileContentArray = NSDictionary(contentsOfFile: filePath)
else {
return
}

As a side note, it's not common to name variables of dictionary types as arrays.

Implicitly unwrapped property warning?

Since Swift 4, ImplicitlyUnwrappedOptional or ! as we knew it, became Optional.

Check:

let a: ImplicitlyUnwrappedOptional<Int> = 1

will spit out the error:

'ImplicitlyUnwrappedOptional' has been renamed to 'Optional'

So instead if we do:

let a: Int! = 1
print(type(of: a)) //will print "Optional<Int>"

It's still Optional<Int> but indicates to the compiler that it can be implicitly unwrapped.

Implicit Unwrapping is Part of a Declaration.


...

consider ! to be a synonym for ? with the addition that it adds a flag on the declaration letting the compiler know that the declared value can be implicitly unwrapped.

Ref: Reimplementation of Implicitly Unwrapped Optionals


Now getting to the main question:

If you do:

let a: Int! = 1

let b: Any = a
print(type(of: b)) //prints "Optional<Int>"

It will give the following warning:

Expression implicitly coerced from 'Int?' to 'Any'

or as per Xcode 11

Coercion of implicitly unwrappable value of type 'Int?' to 'Any' does not unwrap optional

Note here that we tried to get a non-optional Any out of an Int? which means we were basically expecting an Int but just by specifying Any it won't also unwrap the Optional.

It will remain an Optional, and this is the meaning behind that warning.


Solutions:

To handle this warning gracefully, we can do any of the following:

let a: Int! = 1

let b: Any? = a
type(of: b) //Optional<Any>.Type

let c: Any! = a
type(of: c) //Optional<Any>.Type

let d: Any = a!
type(of: d) //Int.Type

EDIT: (based on comment)

! instead of ? have any practical difference for the programmer?

! tells the compiler that it can be implicitly unwrapped so it can help ease in the need for optional chaining.

Example:

  • With ?

    class A {
    var n: Int? = 1
    }

    class B {
    var a: A? = A()
    }

    let b: B? = B()
    print(b?.a?.n)

    /*
    but the following won't compile as compiler
    will not implicitly unwrap optionals

    print(b.a.n)
    */
  • With !

    class A {
    var n: Int! = 1
    }

    class B {
    var a: A! = A()
    }

    let b: B! = B()
    print(b.a.n) //compiler will implicitly unwrap `!` similar to print(b!.a!.n)

    //also... you can still safely unwrap if you want
    print(b?.a?.n)
    • b.a.n and b?.a?.n will both give an Optional<Int> at the end
    • Ofcourse if b or a is nil then b.a.n will crash because it's implicitly unwrapping b and a to get to n which is Optional<Int>
    • To get Int instead of Optional<Int>, you would do b.a.n! and so in your case you would do: print(residenceId!) to get Int

I hope I made sense

Why is it necessary to coerce from Optional to Any?

The purpose of Optional is to prevent you from accidentally calling methods on or accessing properties of variables which are nil.

You are right that Optional can be assigned to Any. Anything can be assigned to Any. But look what happens now! I have transformed a value that can be nil into a non-optional type Any! If somehow this value is passed to somewhere else and some other programmer (or you in the future) would assume that it has a non-nil value.

Therefore, the compiler warning is there to remind you that you may have forgotten to unwrap your optionals.



Related Topics



Leave a reply



Submit