Skip to content

Instantly share code, notes, and snippets.

@acalism
Last active March 6, 2018 07:42
Show Gist options
  • Save acalism/88ed98bd42f54124b6d35551dad2bb25 to your computer and use it in GitHub Desktop.
Save acalism/88ed98bd42f54124b6d35551dad2bb25 to your computer and use it in GitHub Desktop.
Sometimes, String's Range<String.Index> and NSString's NSRange is not compatible. Here is an example.
import Foundation
// Because NSString using UTF-16, so the following answer is suitable.
// Update for Swift 4 (Xcode 9):
extension String {
/// 将 Range 转为 NSRange
///
/// - Parameter range: 要转换的range
/// - Returns: 转换后的结果(如果range合法,那么nsRange就不会是nil)
func nsRange(from range: Range<String.Index>) -> NSRange? {
guard let from = range.lowerBound.samePosition(in: utf16), let to = range.upperBound.samePosition(in: utf16) else {
return nil
}
return NSRange(location: utf16.distance(from: utf16.startIndex, to: from), length: utf16.distance(from: from, to: to))
}
/// 将 NSRange 转换为 Range
///
/// - Parameter nsRange: 要转换的 NSRange
/// - Returns: 转换后的结果
func range(from nsRange: NSRange) -> Range<String.Index>? {
guard let from16 = utf16.index(utf16.startIndex, offsetBy: nsRange.location, limitedBy: utf16.endIndex)
, let to16 = utf16.index(from16, offsetBy: nsRange.length, limitedBy: utf16.endIndex)
, let from = String.Index(from16, within: self)
, let to = String.Index(to16, within: self)
else { return nil }
return from ..< to
}
}
let cafe = "cafe\u{0301}"
cafe.count
cafe.utf16.count
for i in 0 ..< cafe.utf16.count {
let nsRange = NSRange(location: i, length: 1)
if let r = cafe.range(from: nsRange) { // "e" is not a substring, which is different from NSString
let sub = String(cafe[r])
print(cafe[r], "e".contains(sub), r)
} else {
let sub = (cafe as NSString).substring(with: nsRange)
print(sub, "e".contains(sub), i)
}
}
print()
for i in cafe {
print(i)
}
@acalism
Copy link
Author

acalism commented Mar 5, 2018

  1. "e" is not a substring, which is different from NSString;
  2. when coloring "e" using NSAttributedString, "é" is colored.

@acalism
Copy link
Author

acalism commented Mar 5, 2018

总之,String 的 Range<String.Index> 和 NSString 的 NSRange 在能力上不是等价的。主要体现在取子串(substring)和属性字符串(attributedString)这两项能力上。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment