类型 'MatchedValue' 不符合协议 'Decodable'

Type 'MatchedValue' does not conform to protocol 'Decodable'

我有一个必须符合 Codable 协议的结构。 但是,我收到错误消息:

Type 'MatchedValue' does not conform to protocol 'Decodable'**

如何使 String.Index 符合 Codable? 谢谢

struct MatchedValue: Codable {
    let value: String
    let range: Range<String.Index>
  }

尝试使用 Int 而不是 String.Index。

首先,扩展以获取元素或字符串的位置作为 Int 以及使用整数范围的能力:

extension StringProtocol {
    func distance(of element: Element) -> Int? { firstIndex(of: element)?.distance(in: self) }
    
    func distance<S: StringProtocol>(of string: S) -> Int? { range(of: string)?.lowerBound.distance(in: self) }
    
    func substring(with range: Range<Int>) -> String? {
        guard range.lowerBound >= 0 && range.upperBound <= self.count else { return nil }
        
        let lowerBoundStringIndex = self.index(self.startIndex, offsetBy: range.lowerBound)
        let upperBoundStringIndex = self.index(lowerBoundStringIndex, offsetBy: range.upperBound - range.lowerBound)

        return String(self[lowerBoundStringIndex..<upperBoundStringIndex])
    }

    subscript(r: Range<Int>) -> String? { substring(with: r) }
    
    func substring(with range: ClosedRange<Int>) -> String? {
        guard range.lowerBound >= 0 && range.upperBound < self.count else { return nil }
        
        if range.lowerBound == range.upperBound { return "" }
        
        let lowerBoundStringIndex = self.index(self.startIndex, offsetBy: range.lowerBound)
        let upperBoundStringIndex = self.index(lowerBoundStringIndex, offsetBy: range.upperBound + 1 - range.lowerBound)

        return String(self[lowerBoundStringIndex..<upperBoundStringIndex])
    }
    
    subscript(r: ClosedRange<Int>) -> String? { substring(with: r) }
}

extension Collection {
    func distance(to index: Index) -> Int { distance(from: startIndex, to: index) }
}

extension String.Index {
    func distance<S: StringProtocol>(in string: S) -> Int { string.distance(to: self) }
}

现在您可以使用这个新实现了:

let letters = "My string"
letters.count // 9

// get range
let lowerBound: Int? = letters.distance(of: "M")
let upperBound: Int? = letters.distance(of: "g")
let intRange: Range<Int> = lowerBound!..<upperBound!
let intClosedRange: ClosedRange<Int> = lowerBound!...upperBound!

// get substring
letters.substring(with: intRange)           // "My strin"
letters.substring(with: intClosedRange)     // "My string"
// or
letters[intRange]                           // "My strin"
letters[intClosedRange]                     // "My string"

我还包括使用 String.Index 和其他测试的比较。

// For comparison purposes only
let lowerIndex = letters.firstIndex(of: "M")
let upperIndex = letters.firstIndex(of: "g")
let range: Range<String.Index> = lowerIndex!..<upperIndex!
let closedRange: ClosedRange<String.Index> = lowerIndex!...upperIndex!
letters[range]                              // "My strin"
letters[closedRange]                        // "My string"

// Additional implementation tests
letters.substring(with: 3...5)  // "str"
letters.substring(with: 3..<5)  // "st"
letters.substring(with: 0...9)  // nil
letters.substring(with: 0..<9)  // "My string"
letters.substring(with: 2...2)  // ""
letters.substring(with: 2..<2)  // ""

这是我的 gist.