Fast Migration 2 to 3 for Quick Sequence Protocol

I am trying to convert the following code from this library ( https://github.com/dankogai/swift-json ) to Swift 3. Compatible code.

I find it difficult to determine how to convert the Sequence protocol used in Swift 2 with the correct version for Swift 3. I cannot find documentation on changing the Swift 2 Sequence protocol from 3.

Here is the code that I have currently converted as much as possible in 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 } } 

The error I get in the specification is in the attached image.

enter image description here

If you want to play with it, all the code is pretty short for the JSON library. Here it is below:

 // // 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", code:404, userInfo:[ NSLocalizedDescriptionKey: "[\"\(key)\"] not found" ])) default: return JSON(NSError( domain:"JSONErrorDomain", code:500, 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. /// eg 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)> { 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 } } 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", "l", "i", "s": return o.int64Value.description case "Q", "L", "I", "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!") } 
+5
source share
1 answer

In Swift 3, generate() been renamed to makeIterator() . Changing the name of your function should fix the problem. (Note that other names have also changed, such as AnyGenerator β†’ AnyIterator, but it looks like your code has already been taken care of.)

This change was implemented as part of SE-0006: apply API recommendations to the standard library .

+3
source

Source: https://habr.com/ru/post/1257565/


All Articles