Last active
March 6, 2018 07:42
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} |
Author
acalism
commented
Mar 5, 2018
•
- "e" is not a substring, which is different from NSString;
- when coloring "e" using NSAttributedString, "é" is colored.
总之,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