cocoatextkit

Compare NSTextRange for equality


Given two NSTextRange's with custom NSTextLocation's, how would we compare them for equality?

class Location: NSObject, NSTextLocation {
    let value: Int

    func compare(_ location: NSTextLocation) -> ComparisonResult {
        guard let location = location as? Location else {
            fatalError("Expected Location")
        }

        if self.value == location.value {
            return .orderedSame
        } else if self.value < location.value {
            return .orderedAscending
        } else {
            return .orderedDescending
        }
    }

    init(_ value: Int) {
        self.value = value
    }
}

let textRange1 = NSTextRange(location: Location(1), end: Location(2))!
let textRange2 = NSTextRange(location: Location(1), end: Location(2))!

print("startLocations are equal: \(textRange1.location.compare(textRange2.location) == .orderedSame)")
print("endLocations are equal: \(textRange1.endLocation.compare(textRange2.endLocation) == .orderedSame)")
print("ranges are equal: \(textRange1.isEqual(to: textRange2))")

In the above example, the start and end locations of the two NSTextRanges compare to be .orderedSame. But, the comparison for equality against the two ranges fails. I was expecting them to be equal.

How do we compare them for equality?


Solution

  • textRange1.isEqual(to: textRange2) does textRange1.location.isEqual(to: textRange2.location) and textRange1.endLocation.isEqual(to: textRange2.endLocation).

    isEqual(_:) is a method of NSObjectProtocol, inherited by NSTextLocation. Implement it in Location to make textRange1.isEqual(to: textRange2) work.

    override func isEqual(_ object: Any?) -> Bool {
        guard let location = object as? Location else {
            fatalError("Expected Location")
        }
        return self.value == location.value
    }