Swift结构扩展添加初始值设定项
我正在尝试将初始值设定项添加到Swift结构扩展添加初始值设定项,swift,compiler-errors,range,Swift,Compiler Errors,Range,我正在尝试将初始值设定项添加到范围 import Foundation extension Range { init(_ range: NSRange, in string: String) { let lower = string.index(string.startIndex, offsetBy: range.location) let upper = string.index(string.startIndex, offsetBy: NSMaxRa
范围
import Foundation
extension Range {
init(_ range: NSRange, in string: String) {
let lower = string.index(string.startIndex, offsetBy: range.location)
let upper = string.index(string.startIndex, offsetBy: NSMaxRange(range))
self.init(uncheckedBounds: (lower: lower, upper: upper))
}
}
但是,最后一行有一个Swift编译器错误
无法将类型为“(下:String.Index,上:String.Index)”的值(也称为“(下:String.CharacterView.Index,上:String.CharacterView.Index)”转换为所需的参数类型“(下:上:下)”
如何编译它?问题是,即使
String.Index
符合Comparable
协议,您仍然需要指定要使用的范围类型公共结构范围,其中绑定:Comparable{}
注意:由于NSString
使用UTF-16,请检查,并且在您提到的中,对于包含多个UTF-16码点的字符,您的初始代码无法正常工作。以下是Swift 3的更新工作版本
extension Range where Bound == String.Index {
init(_ range: NSRange, in string: String) {
let lower16 = string.utf16.index(string.utf16.startIndex, offsetBy: range.location)
let upper16 = string.utf16.index(string.utf16.startIndex, offsetBy: NSMaxRange(range))
if let lower = lower16.samePosition(in: string),
let upper = upper16.samePosition(in: string) {
self.init(lower..<upper)
} else {
fatalError("init(range:in:) could not be implemented")
}
}
}
let string = "❄️Let it snow! ☃️"
let range1 = NSRange(location: 0, length: 1)
let r1 = Range<String.Index>(range1, in: string) // ❄️
let range2 = NSRange(location: 1, length: 2)
let r2 = Range<String.Index>(range2, in: string) // fatal error: init(range:in:) could not be implemented
该方法的签名需要“绑定”类型(至少在swift 4中) 由于Bound只是一个关联的“Comparable”类型,String.Index也符合它,所以您应该能够强制转换它
extension Range {
init(_ range: NSRange, in string: String) {
let lower : Bound = string.index(string.startIndex, offsetBy: range.location) as! Bound
let upper : Bound = string.index(string.startIndex, offsetBy: NSMaxRange(range)) as! Bound
self.init(uncheckedBounds: (lower: lower, upper: upper))
}
}
您需要将范围初始值设定项约束到Bound等于String.Index的位置,获取NSRange utf16索引,并在字符串中找到与字符串索引相同的位置,如下所示:
extension Range where Bound == String.Index {
init?(_ range: NSRange, in string: String) {
guard
let start = string.utf16.index(string.utf16.startIndex, offsetBy: range.location, limitedBy: string.utf16.endIndex),
let end = string.utf16.index(string.utf16.startIndex, offsetBy: range.location + range.length, limitedBy: string.utf16.endIndex),
let startIndex = start.samePosition(in: string),
let endIndex = end.samePosition(in: string)
else {
return nil
}
self = startIndex..<endIndex
}
}
扩展范围,其中Bound==String.Index{
初始化?(uu范围:NSRange,在字符串中:string){
警卫
让start=string.utf16.index(string.utf16.startIndex,offsetBy:range.location,limitedBy:string.utf16.endIndex),
让end=string.utf16.index(string.utf16.startIndex,offsetBy:range.location+range.length,limitedBy:string.utf16.endIndex),
让startIndex=start.samePosition(in:string),
让endIndex=end.samePosition(in:string)
否则{
归零
}
self=startIndex..Related:我不明白你为什么需要使用UTF-16编码的string
。我的初始代码似乎工作正常,即使是带有emojis的字符串。请提供一个反例。回答你的问题需要很长的注释,所以我决定更新我的答案。我还对我的示例进行了一些编辑,使之有所不同更明显的是,我当然看到了区别,但我仍然不明白为什么你的例子中的结果是正确的。我想我会相信苹果的话。谢谢!:-)
extension Range where Bound == String.Index {
init?(_ range: NSRange, in string: String) {
guard
let start = string.utf16.index(string.utf16.startIndex, offsetBy: range.location, limitedBy: string.utf16.endIndex),
let end = string.utf16.index(string.utf16.startIndex, offsetBy: range.location + range.length, limitedBy: string.utf16.endIndex),
let startIndex = start.samePosition(in: string),
let endIndex = end.samePosition(in: string)
else {
return nil
}
self = startIndex..<endIndex
}
}