I'm attempting to determine the indexes of occurrences of a given string in a String
, then generate an NSRange
using those indexes in order to add attributes to an NSMutableAttributedString
. The problem is rangeOfString
returns Range<Index>
but addAttributes:range:
expects an NSRange
. My attempts to create an NSRange
from the start and end indexes of the Range
have failed, because String.CharacterView.Index
is not an Int
, thus it will not compile.
How can one use Range<Index>
values to create an NSRange
?
var originalString = "Hello {world} and those who inhabit it."
let firstBraceIndex = originalString.rangeOfString("{") //Range<Index>
let firstClosingBraceIndex = originalString.rangeOfString("}")
let range = NSMakeRange(firstBraceIndex.startIndex, firstClosingBraceIndex.endIndex)
//compile time error: cannot convert value of type Index to expected argument type Int
let attributedString = NSMutableAttributedString(string: originalString)
attributedString.addAttributes([NSFontAttributeName: boldFont], range: range)
If you start with your original string cast as a Cocoa NSString:
var originalString = "Hello {world} and those who inhabit it." as NSString
... then your range results will be NSRange and you'll be able to hand them back to Cocoa.
To make an NSRange you need to get the starting location and length of the range as ints. You can do this using the distance(from:to:)
method on your originalString
:
let rangeStartIndex = firstBraceIndex!.lowerBound
let rangeEndIndex = firstClosingBraceIndex!.upperBound
let start = originalString.distance(from: originalString.startIndex, to: rangeStartIndex)
let length = originalString.distance(from: rangeStartIndex, to: rangeEndIndex)
let nsRange = NSMakeRange(start, length)
let attributedString = NSMutableAttributedString(string: originalString)
attributedString.addAttributes([NSFontAttributeName: boldFont], range: nsRange)
To get the startingLocation, get the distance from the originalString
's startIndex, to the starting index of the range you want (which in your case would be the firstBraceIndex.lowerBound
if you want to include the {
, or firstBraceIndex.upperBound
if you don't). Then to get the length of your range, get the distance from your range's starting index to its ending index.
I just force unwrapped your firstBraceIndex
and firstClosingBraceIndex
to make the code easier to read, but of course it would be better to properly deal with these potentially being nil.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With