Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'Int' is not identical to 'String.Index'

As an exercise I am rewriting one of my apps using Swift.

In Objective-C I had the following line of code:

NSRange extendedRange = NSUnionRange(range, [[self.backingStore string]lineRangeForRange:NSMakeRange(NSMaxRange(range), 0)]);

In swift it looks like this:

let str = backingStore.string
let extendedRange: NSRange = NSUnionRange(range, str.lineRangeForRange(NSMakeRange(NSMaxRange(range), 0)))

However, for some reason I am getting 'Int' is not identical to 'String.Index' and I can't figure out why. Any help / insight would be appreciated.


EDIT:

If I bridge my string, it works:

let str = backingStore.string
let extendedRange: NSRange = NSUnionRange(range, str.bridgeToObjectiveC().lineRangeForRange(NSMakeRange(NSMaxRange(range), 0)))
like image 395
Michael Avatar asked Nov 10 '22 06:11

Michael


1 Answers

Swift strings are not the same as Foundation strings: they can be bridged, and they may have method names in common, but that does not mean they should be treated as being compatible. Here are two views of the type definition of Swift.String.lineRangeForRange.

Swift.String.lineRangeForRange (Swift.String)(Swift.Range<Swift.String.Index>) -> Swift.Range<Swift.String.Index>

String -> (Range<String.Index>) -> Range<String.Index>

Note also that Swift's Range<T> is start/end while Foundation's NSRange is location/length. There are ways to convert between NSRange and Range<Int>, but a Range<String.Index> is a different story: String.Index is more like an "iterator" than an "index".

What I'd say (and I'm highly pragmatic about this sort of thing) is that if you have a block of code that is based on the semantics of Objective-C strings it might be good to keep using them for a while: get your code working, and then evaluate changing to Swift's String later.

like image 125
Jay Freeman -saurik- Avatar answered Nov 15 '22 06:11

Jay Freeman -saurik-