String or NSString, which one ought to be

Allen
Allen
Jul 24, 2017 · 2 min read

As a modern programming-language, Swift has been rapidly rising in popularity for past years. Although adopting Swift enormously in production development can bring advantages in many aspects, it’s still unavoidable to interoperate with framework or library based on Objective-C sometimes. For instance, String or NSString, which one ought to be adopted or better fit into our current development?

Use native types whenever possible

In general, you should use the Swift native types as possible as you can because they are optimized to compile for better performance. But wait, I just said unavoidable, right? Let’s take a look at an Objective-C based class NSRegularExpression as an example.

let str = "Hello, playground"
do {
let expression = try NSRegularExpression(pattern: "\\s{1,}",
options: [.anchorsMatchLines])
let range = NSRange(location: 0,
length: str.characters.count)
let matches = expression.matches(in: str,
options: [],
range: range)
for match in matches {
print(match)
}
} catch {
print(error.localizedDescription)
}

In above snippet, we can see the function func matches(in string: String, options: NSRegularExpression.MatchingOptions = [], range: NSRange) -> [NSTextCheckingResult] which only accepts NSRange variable as a parameter; therefore, translating Range type str.startIndex..<str.endIndex to NSRange class will be undoubtedly necessary once we have our codes interoperate and be mixed up String, NSString, Range and NSRange. However, an experienced Swift programmer might find there is a lethal flaw in above snippet also. It's about the way of calculating string length, str.characters.count. The practice like this is highly error prone because Swift uses Extended Grapheme Clusters. Ex, a Unicode smiley symbol. Swift sees it as one character, but the NSString method sees it as two.

So… is there a principal or suggestion?

If we don’t want to pay too much attention on the difference like this, for risk-free, my suggestion is always to cast String to NSString once facing Objective-C based function, like NSRegularExpression. Of course, the strategy will not be necessary until native Swift function is introduced, ex. we might see RegularExpression someday.

So, in order to fix above flaw. The way to calculate length should be like the snippet below. All in all, there are always native ways to deal with variables; however, a risk-free or less error prone strategy can save us a day sometimes :)

// Option 1: Cast String to NSString
let range = NSRange(location: 0,
length: (str as NSString).length)

// Option 2: Calculate utf16 count when accessing on a Swift String value.
let range = NSRange(location: 0,
length: str.utf16.count)
Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade