3

I'm pulling my hair out trying to generate a valid NSRange, it doesn't seem like it should be this complicated so I'm guessing I'm using the wrong approach. Here is what I'm trying to do:

I have a string with some unicode character in it:

"The quick brown fox\n❄jumped\n❄over the lazy dog"

I want to create an NSRange from that character until the end of string, and while I can get the corresponding index for the first occurrence of the character:

text.rangeOfString("❄")?.startIndex

I can't seem to get the end of the string in a consistent format (something that I can pass to NSMakeRange) to actually generate the range. This seems like it should be pretty simple, yet I've been stuck for over an hour now trying to figure out how to get it to work, I keep ending up with Index types that I can't cast to integers to convert back to length that NSMakeRange requires for its second element.

Ideally I'd do something like this (which is invalid due to incompatible and non-castable types (Index vs Int)):

let start = text.rangeOfString("❄")?.startIndex
NSMakeRange(start, text.endIndex - start)

I am using Swift, so I have the ability to use Swift's Range<String.Index>, if it will make things easier, although it seems to be yet another range representation different from NSRange and I'm not sure how compatible the two are (don't want to run into another dimension of Index vs Int).

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Alexander Tsepkov
  • 3,946
  • 3
  • 35
  • 59
  • 1
    Cast your String as NSString then you can use Foundation's .rangeOfString (instead of Swift's .rangeOfString) which will return an NSRange. Be careful though, it doesn't work with Unicode the same as Swift's method, and NSRange and Range are not compatible (although there's hacks to go back and forth between the two). – Eric Aya May 25 '16 at 15:34
  • NSMakeRange(start, text.characters.count - start) will do the magic' – Muhammad Ali May 25 '16 at 16:08
  • Thanks Eric, I think a lot of the confusion was because I didn't realize the two `.rangeOfString` methods were unrelated. Do you want to throw that in an answer and I can accept it? – Alexander Tsepkov May 25 '16 at 16:32
  • Casting the String to NSString is probably the easiest solution (similar issue here: http://stackoverflow.com/a/26517690/1187415 or here: http://stackoverflow.com/a/27041376/1187415), but you *can* convert a String Range to NSRange and back (with full Unicode support): http://stackoverflow.com/a/30404532/1187415. – Martin R May 25 '16 at 17:12
  • I've made an answer from my comment and also linked to Martin R's useful range conversion post. – Eric Aya May 25 '16 at 18:22

1 Answers1

2

Cast your String as NSString.

You will be able to use Foundation's .rangeOfString instead of Swift's .rangeOfString.

The Foundation's one will return an NSRange.

Be careful though, it doesn't work the same as Swift's method with Unicode, and NSRange and Range are not compatible (although there's ways to convert them).

Community
  • 1
  • 1
Eric Aya
  • 69,473
  • 35
  • 181
  • 253