快速序列协议的Swift 2到3迁移
发布时间:2020-12-14 02:24:11 所属栏目:百科 来源:网络整理
导读:我正在尝试将以下代码从此库( https://github.com/dankogai/swift-json)转换为Swift 3兼容代码. 我很难弄清楚如何将Swift 2中使用的Sequence协议转换为Swift 3的正确版本.我找不到任何关于Swift 2 Sequence协议变化的文档与3相比. 这是我目前已尽可能转换为S
我正在尝试将以下代码从此库(
https://github.com/dankogai/swift-json)转换为Swift 3兼容代码.
我很难弄清楚如何将Swift 2中使用的Sequence协议转换为Swift 3的正确版本.我找不到任何关于Swift 2 Sequence协议变化的文档与3相比. 这是我目前已尽可能转换为Swift 3的代码 extension JSON : Sequence { public func generate()->AnyIterator<(AnyObject,JSON)> { switch _value { case let o as NSArray: var i = -1 return AnyIterator { i=i+1 if i == o.count { return nil } return (i as AnyObject,JSON(o[i])) } case let o as NSDictionary: var ks = Array(o.allKeys.reversed()) return AnyIterator { if ks.isEmpty { return nil } if let k = ks.removeLast() as? String { return (k as AnyObject,JSON(o.value(forKey: k)!)) } else { return nil } } default: return AnyIterator{ nil } } } public func mutableCopyOfTheObject() -> AnyObject { return _value.mutableCopy as AnyObject } } 我在具体细节中得到的错误在附图中. 如果你想玩它,整个代码对于JSON库来说相当短.它在下面: // // json.swift // json // // Created by Dan Kogai on 7/15/14. // Copyright (c) 2014 Dan Kogai. All rights reserved. // import Foundation /// init public class JSON { public let _value:AnyObject /// unwraps the JSON object public class func unwrap(obj:AnyObject) -> AnyObject { switch obj { case let json as JSON: return json._value case let ary as NSArray: var ret = [AnyObject]() for v in ary { ret.append(unwrap(obj: v as AnyObject)) } return ret as AnyObject case let dict as NSDictionary: var ret = [String:AnyObject]() for (ko,v) in dict { if let k = ko as? String { ret[k] = unwrap(obj: v as AnyObject) } } return ret as AnyObject default: return obj } } /// pass the object that was returned from /// NSJSONSerialization public init(_ obj:Any) { self._value = JSON.unwrap(obj: obj as AnyObject) } /// pass the JSON object for another instance public init(_ json:JSON){ self._value = json._value } } /// class properties extension JSON { public typealias NSNull = Foundation.NSNull public typealias NSError = Foundation.NSError public class var null:NSNull { return NSNull() } /// constructs JSON object from data public convenience init(data:NSData) { var err:NSError? var obj:Any? do { obj = try JSONSerialization.jsonObject( with: data as Data,options:[]) } catch let error as NSError { err = error obj = nil } self.init(err != nil ? err! : obj!) } /// constructs JSON object from string public convenience init(string:String) { let enc:String.Encoding = String.Encoding.utf8 self.init(data: string.data(using: enc)! as NSData) } /// parses string to the JSON object /// same as JSON(string:String) public class func parse(string:String)->JSON { return JSON(string:string) } /// constructs JSON object from the content of NSURL public convenience init(nsurl:NSURL) { var enc:String.Encoding = String.Encoding.utf8 do { let str = try NSString(contentsOf:nsurl as URL,usedEncoding:&enc.rawValue) self.init(string:str as String) } catch let err as NSError { self.init(err) } } /// fetch the JSON string from NSURL and parse it /// same as JSON(nsurl:NSURL) public class func fromNSURL(nsurl:NSURL) -> JSON { return JSON(nsurl:nsurl) } /// constructs JSON object from the content of URL public convenience init(url:String) { if let nsurl = NSURL(string:url) as NSURL? { self.init(nsurl:nsurl) } else { self.init(NSError( domain:"JSONErrorDomain",code:400,userInfo:[NSLocalizedDescriptionKey: "malformed URL"] ) ) } } /// fetch the JSON string from URL in the string public class func fromURL(url:String) -> JSON { return JSON(url:url) } /// does what JSON.stringify in ES5 does. /// when the 2nd argument is set to true it pretty prints public class func stringify(obj:AnyObject,pretty:Bool=false) -> String! { if !JSONSerialization.isValidJSONObject(obj) { let error = JSON(NSError( domain:"JSONErrorDomain",code:422,userInfo:[NSLocalizedDescriptionKey: "not an JSON object"] )) return JSON(error).toString(pretty: pretty) } return JSON(obj).toString(pretty: pretty) } } /// instance properties extension JSON { /// access the element like array public subscript(idx:Int) -> JSON { switch _value { case _ as NSError: return self case let ary as NSArray: if 0 <= idx && idx < ary.count { return JSON(ary[idx]) } return JSON(NSError( domain:"JSONErrorDomain",code:404,userInfo:[ NSLocalizedDescriptionKey: "[(idx)] is out of range" ])) default: return JSON(NSError( domain:"JSONErrorDomain",code:500,userInfo:[ NSLocalizedDescriptionKey: "not an array" ])) } } /// access the element like dictionary public subscript(key:String)->JSON { switch _value { case _ as NSError: return self case let dic as NSDictionary: if let val:Any = dic[key] { return JSON(val) } return JSON(NSError( domain:"JSONErrorDomain",userInfo:[ NSLocalizedDescriptionKey: "["(key)"] not found" ])) default: return JSON(NSError( domain:"JSONErrorDomain",userInfo:[ NSLocalizedDescriptionKey: "not an object" ])) } } /// access json data object public var data:AnyObject? { return self.isError ? nil : self._value } /// Gives the type name as string. /// e.g. if it returns "Double" /// .asDouble returns Double public var type:String { switch _value { case is NSError: return "NSError" case is NSNull: return "NSNull" case let o as NSNumber: switch String(cString:o.objCType) { case "c","C": return "Bool" case "q","l","i","s": return "Int" case "Q","L","I","S": return "UInt" default: return "Double" } case is NSString: return "String" case is NSArray: return "Array" case is NSDictionary: return "Dictionary" default: return "NSError" } } /// check if self is NSError public var isError: Bool { return _value is NSError } /// check if self is NSNull public var isNull: Bool { return _value is NSNull } /// check if self is Bool public var isBool: Bool { return type == "Bool" } /// check if self is Int public var isInt: Bool { return type == "Int" } /// check if self is UInt public var isUInt: Bool { return type == "UInt" } /// check if self is Double public var isDouble: Bool { return type == "Double" } /// check if self is any type of number public var isNumber: Bool { if let o = _value as? NSNumber { let t = String(cString:o.objCType) return t != "c" && t != "C" } return false } /// check if self is String public var isString: Bool { return _value is NSString } /// check if self is Array public var isArray: Bool { return _value is NSArray } /// check if self is Dictionary public var isDictionary: Bool { return _value is NSDictionary } /// check if self is a valid leaf node. public var isLeaf: Bool { return !(isArray || isDictionary || isError) } /// gives NSError if it holds the error. nil otherwise public var asError:NSError? { return _value as? NSError } /// gives NSNull if self holds it. nil otherwise public var asNull:NSNull? { return _value is NSNull ? JSON.null : nil } /// gives Bool if self holds it. nil otherwise public var asBool:Bool? { switch _value { case let o as NSNumber: switch String(cString:o.objCType) { case "c","C": return Bool(o.boolValue) default: return nil } default: return nil } } /// gives Int if self holds it. nil otherwise public var asInt:Int? { switch _value { case let o as NSNumber: switch String(cString:o.objCType) { case "c","C": return nil default: return Int(o.int64Value) } default: return nil } } /// gives Int32 if self holds it. nil otherwise public var asInt32:Int32? { switch _value { case let o as NSNumber: switch String(cString:o.objCType) { case "c","C": return nil default: return Int32(o.int64Value) } default: return nil } } /// gives Int64 if self holds it. nil otherwise public var asInt64:Int64? { switch _value { case let o as NSNumber: switch String(cString:o.objCType) { case "c","C": return nil default: return Int64(o.int64Value) } default: return nil } } /// gives Float if self holds it. nil otherwise public var asFloat:Float? { switch _value { case let o as NSNumber: switch String(cString:o.objCType) { case "c","C": return nil default: return Float(o.floatValue) } default: return nil } } /// gives Double if self holds it. nil otherwise public var asDouble:Double? { switch _value { case let o as NSNumber: switch String(cString:o.objCType) { case "c","C": return nil default: return Double(o.doubleValue) } default: return nil } } // an alias to asDouble public var asNumber:Double? { return asDouble } /// gives String if self holds it. nil otherwise public var asString:String? { switch _value { case let o as NSString: return o as String default: return nil } } /// if self holds NSArray,gives a [JSON] /// with elements therein. nil otherwise public var asArray:[JSON]? { switch _value { case let o as NSArray: var result = [JSON]() for v:Any in o { result.append(JSON(v)) } return result default: return nil } } /// if self holds NSDictionary,gives a [String:JSON] /// with elements therein. nil otherwise public var asDictionary:[String:JSON]? { switch _value { case let o as NSDictionary: var result = [String:JSON]() for (ko,v): (Any,Any) in o { if let k = ko as? String { result[k] = JSON(v) } } return result default: return nil } } /// Yields date from string public var asDate:NSDate? { if let dateString = _value as? String { let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZ" return dateFormatter.date(from: dateString) as NSDate? } return nil } /// gives the number of elements if an array or a dictionary. /// you can use this to check if you can iterate. public var count:Int { switch _value { case let o as NSArray: return o.count case let o as NSDictionary: return o.count default: return 0 } } public var length:Int { return self.count } // gives all values content in JSON object. public var allValues:JSON{ if(self._value.allValues == nil) { return JSON([]) } return JSON(self._value.allValues) } // gives all keys content in JSON object. public var allKeys:JSON{ if(self._value.allKeys == nil) { return JSON([]) } return JSON(self._value.allKeys) } } extension JSON : Sequence { public func generate()->AnyIterator<(AnyObject,JSON(o.value(forKey: k)!)) } else { return nil } } default: return AnyIterator{ nil } } } public func mutableCopyOfTheObject() -> AnyObject { return _value.mutableCopy as AnyObject } } extension JSON : CustomStringConvertible { /// stringifies self. /// if pretty:true it pretty prints public func toString(pretty:Bool=false)->String { switch _value { case is NSError: return "(_value)" case is NSNull: return "null" case let o as NSNumber: switch String(cString:o.objCType) { case "c","C": return o.boolValue.description case "q","s": return o.int64Value.description case "Q","S": return o.uint64Value.description default: switch o.doubleValue { case 0.0/0.0: return "0.0/0.0" // NaN case -1.0/0.0: return "-1.0/0.0" // -infinity case +1.0/0.0: return "+1.0/0.0" // infinity default: return o.doubleValue.description } } case let o as NSString: return o.debugDescription default: let opts = pretty ? JSONSerialization.WritingOptions.prettyPrinted : JSONSerialization.WritingOptions() if let data = (try? JSONSerialization.data( withJSONObject: _value,options:opts)) as NSData? { if let result = NSString( data:data as Data,encoding:String.Encoding.utf8.rawValue ) as? String { return result } } return "YOU ARE NOT SUPPOSED TO SEE THIS!" } } public var description:String { return toString() } } extension JSON : Equatable {} public func ==(lhs:JSON,rhs:JSON)->Bool { // print("lhs:(lhs),rhs:(rhs)") if lhs.isError || rhs.isError { return false } else if lhs.isLeaf { if lhs.isNull { return lhs.asNull == rhs.asNull } if lhs.isBool { return lhs.asBool == rhs.asBool } if lhs.isNumber { return lhs.asNumber == rhs.asNumber } if lhs.isString { return lhs.asString == rhs.asString } } else if lhs.isArray { for i in 0..<lhs.count { if lhs[i] != rhs[i] { return false } } return true } else if lhs.isDictionary { for (k,v) in lhs.asDictionary! { if v != rhs[k] { return false } } return true } fatalError("JSON == JSON failed!") }
在Swift 3中,generate()已重命名为makeIterator().更改函数名称应该可以解决问题. (请注意,其他名称也已更改,例如AnyGenerator→AnyIterator,但看起来已经在您的代码中处理过了.)
此更改已作为SE-0006: Apply API Guidelines to the Standard Library的一部分实施. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |