Zigii Wong
Zigii Wong

Reputation: 7826

Compare value and return a bool in Swift

I am converting my code from Objective-C to Swift. I declared a function to compare values of two properties and return a Bool. And I am confused about why this code not work in Swift.

private var currentLineRange: NSRange?
var location: UInt?

func atBeginningOfLine() -> Bool {
    return self.location! == self.currentLineRange?.location ? true : false
}

Compiler gave me an error:

Could not find an overload for == that accepts the supplied arguments

Thanks.

Upvotes: 1

Views: 3215

Answers (2)

Airspeed Velocity
Airspeed Velocity

Reputation: 40965

You have two optional values and you want to check if they’re equal. There is a version of == for comparing two optionals – but they need to be of the same type.

The main problem here is that you are comparing NSRange.location, which is a Int, with location, which is a UInt. If you tried to do this even without the complication of the optionals, you’d get an error:

let ui: UInt = 1
let i: Int = 1
// error: binary operator '==' cannot be applied to operands of 
// type 'Int' and ‘UInt'
i == ui  

There’s two ways you can go. Either change location to be an Int, and you’ll be able to use the optional ==:

private var currentLineRange: NSRange?
var location: Int?

func atBeginningOfLine() -> Bool {
    // both optionals contain Int, so you can use == on them:
    return location == currentLineRange?.location
}

Or, if location really does need to be a UInt for some other reason, map one of the optionals to the type of the other to compare them:

private var currentLineRange: NSRange?
var location: UInt?

func atBeginningOfLine() -> Bool {
    return location.map { Int($0) } == currentLineRange?.location
}

One thing to be careful of – nil is equal to nil. So if you don’t want this (depends on the logic you’re going for), you need to code for it explicitly:

func atBeginningOfLine() -> Bool {
    if let location = location, currentLineRange = currentLineRange {
        // assuming you want to stick with the UInt
        return Int(location) == currentLineRange.location
    }
    return false // if either or both are nil
}

Upvotes: 1

Rob
Rob

Reputation: 11733

Swift has operator overloading, so == is a function. You have to define a function that takes your two types.

If you remove the UInt it works:

class Document {
    private var currentLineRange: NSRange?
    var location: Int?

    func atBeginningOfLine() -> Bool {
        if let currentLocation = self.location, lineRange = self.currentLineRange {
            return currentLocation=lineRange?.location
        } else {
            return false
        }
    }
}

Modified to be null safe.

Upvotes: 1

Related Questions