Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a difference between == true and != false in swift?

I had this code in my Swift App

func parseJSON() {

    let urlString = "www.websitethatlinkstoJSONfile.com"

    if NSURL(string: urlString) == true {
        let url = NSURL(string: urlString)
        let data = try? NSData(contentsOfURL: url!, options: []) as NSData
        let json = NSData(data: data!)

// more code

However, even though the link actually worked and was true, the if statement was never met and it kept skipping it and moving to else. So I changed the code to

if NSURL(string: urlString) != false 

and it worked perfectly. I'm not sure why though?

like image 797
cheesydoritosandkale Avatar asked Jan 24 '26 17:01

cheesydoritosandkale


2 Answers

As already explained in the other answers, comparing the optional NSURL? against true or false is not what you want, and you should use optional binding instead.

But why does it compile at all? And how can the result be interpreted?

In NSURL(string: urlString) == true, the left-hand side has the type NSURL?, and NSURL is a subclass of NSObject. There is a == operator taking two optional operands:

public func ==<T : Equatable>(lhs: T?, rhs: T?) -> Bool

The compiler uses the implicit conversion of Bool to NSNumber to make that compile. So your code is equivalent to

if NSURL(string: urlString) == NSNumber(bool: true)

and that will always be false, and

if NSURL(string: urlString) != NSNumber(bool: false)

will always be true, simply because the left-hand side is not a number.

Here is a demonstration of the effect:

func foo(x: NSObject?) {
    print(x == true, x == false)
}

foo(NSNumber(bool: true))  // true, false
foo(NSNumber(bool: false)) // false, true
foo(NSObject())            // false, false  !!!

The last case is what you observed: Both x == true and x == false return false.

For classes not inheriting from NSObject it would not compile:

class A { }
let a: A? = A()
if a == true { } // cannot convert value of type 'A?' to expected argument type 'Bool'

Remark: This is another argument for not comparing boolean values against true or false, i.e.

 if a == true && b == false { ... }

is better written as

 if a && !b { ... }

Applied to your case, you would get a compiler error indicating the problem:

let urlString = "http://www.websitethatlinkstoJSONfile.com"
if NSURL(string: urlString) {  }
// error: optional type '_' cannot be used as a boolean; test for '!= nil' instead
like image 169
Martin R Avatar answered Jan 26 '26 06:01

Martin R


You don't really want to check for a boolean value when creating a NSURL, but rather make sure the NSURL you create is non-nil. Try wrapping it it in an if let statement like so to make sure whatever URL's you create are non-nil before executing further code.

   let urlString = "www.websitethatlinkstoJSONfile.com"

    if let url = NSURL(string: urlString) {
       if let data = try? NSData(contentsOfURL: url, options: []) {
           let json = NSData(data: data)
       } else { 
          //Handle case where data is nil
       }
    } else { 
        //Handle case where url is nil 
    }

Using if let statements in this way makes sure that the NSURL and NSData objects you are creating are non-nil and valid objects and then you can add an else statement to them to handle cases where your url or data objects are nil. This will save you from unwanted crashes due to force unwrapping with the ! operator.

like image 40
NSGangster Avatar answered Jan 26 '26 07:01

NSGangster



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!