Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift结构扩展添加初始值设定项_Swift_Compiler Errors_Range - Fatal编程技术网

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
    }
}