我需要使用以下结构:
import Foundation
protocol QueryValueConvertible {
func itemsWith(name: String) -> [URLQueryItem]
}
struct QueryList : QueryValueConvertible {
var elements: [(String, QueryValueConvertible)]
init(elements: [(String, QueryValueConvertible)]) {
self.elements = elements
}
var isEmpty: Bool {
return elements.isEmpty
}
var percentEncodedQuery: String {
let allowedCharacters = QueryList.percentEncodedQueryAllowedCharacters
return items.map { (item) -> String in
guard let encodedName = item.name.addingPercentEncoding(withAllowedCharacters: allowedCharacters) else {
return ""
}
if let value = item.value, let encodedValue = value.addingPercentEncoding(withAllowedCharacters: allowedCharacters) {
return encodedName + "=" + encodedValue
} else {
return encodedName
}
}.joined(separator: "&")
}
var items: [URLQueryItem] {
return elements.flatMap { (name, value) -> [URLQueryItem] in
return value.itemsWith(name: name)
}
}
func itemsWith(name: String) -> [URLQueryItem] {
let prefix = name
guard !elements.isEmpty else {
return [URLQueryItem(name: "\(name)[]", value: nil)]
}
return elements.flatMap { (suffix, value) -> [URLQueryItem] in
let name = "\(prefix)[\(suffix)]"
return value.itemsWith(name: name)
}
}
private static let percentEncodedQueryAllowedCharacters: CharacterSet = { () -> CharacterSet in
// We are far more conservative than NSURLComponents because nobody implements RFC 3986.
// HTML5 allows the following restricted set of characters to appear in query.
// cf: http://www.w3.org/TR/html5/forms.html#application/x-www-form-urlencoded-encoding-algorithm
let characters = NSMutableCharacterSet()
characters.addCharacters(in: NSRange(location: 0x2a, length: 1)) // *
characters.addCharacters(in: NSRange(location: 0x2d, length: 1)) // -
characters.addCharacters(in: NSRange(location: 0x2e, length: 1)) // .
characters.addCharacters(in: NSRange(location: 0x30, length: 10)) // 0-9
characters.addCharacters(in: NSRange(location: 0x41, length: 26)) // A-Z
characters.addCharacters(in: NSRange(location: 0x5f, length: 1)) // _
characters.addCharacters(in: NSRange(location: 0x61, length: 26)) // a-z
return characters as CharacterSet
}()
}
extension QueryList : ExpressibleByDictionaryLiteral {
init(dictionaryLiteral elements: (String, QueryValueConvertible)...) {
self.elements = elements
}
init<S : Sequence>(_ elements: S)
where S.Iterator.Element == (String, QueryValueConvertible)
{
self.elements = Array(elements)
}
}
extension QueryList : ExpressibleByArrayLiteral {
init(arrayLiteral elements: QueryValueConvertible...) {
self.elements = elements.enumerated().map { (index, value) in (String(index), value) }
}
init<S : Sequence>(_ elements: S)
where S.Iterator.Element : QueryValueConvertible
{
self.elements = elements.enumerated().map { (index, value) in (String(index), value) }
}
}
func + (lhs: QueryList, rhs: QueryList) -> QueryList {
return QueryList(elements: lhs.elements + rhs.elements)
}
func += (lhs: inout QueryList, rhs: QueryList) {
lhs = QueryList(elements: lhs.elements + rhs.elements)
}
extension String : QueryValueConvertible {
func itemsWith(name: String) -> [URLQueryItem] {
return [URLQueryItem(name: name, value: self)]
}
}
extension Int : QueryValueConvertible {
func itemsWith(name: String) -> [URLQueryItem] {
return [URLQueryItem(name: name, value: String(self))]
}
}
extension Bool : QueryValueConvertible {
func itemsWith(name: String) -> [URLQueryItem] {
return [URLQueryItem(name: name, value: self ? "true" : "false")]
}
}
在另一个班级中,我有以下代码:
var sampleData = [
"foo": someString,
"bar": anotherString
] as QueryList
let myDict: [String: Bool] = ["example": true]
var myArray = [[String:Any]]()
myArray.append(myDict)
sampleData += ["myData": myArray as! QueryValueConvertible]// this is where the error is occurring.
当我运行我的代码时,我收到以下错误:
Could not cast value of type 'Swift.Array<Swift.Dictionary<Swift.String, Any>>' (0x608000a9bb40) to 'QueryValueConvertible' (0x6080004709d8).
我该如何解决这个问题?
答案 0 :(得分:1)
施法是一种启示,而不是改变;你不能施展到已经不存在的东西。因此,除非myArray as! QueryValueConvertible
已经 一个QueryValueConvertible,否则您无法说myArray
。
嗯,它不是。您只有三种符合QueryValueConvertible的类型:String,Int和Bool。 myArray
不是那些 - 它是一个阵列!所以强迫施法自然会失败,你就会崩溃。