In fact SwiftJSON source altogether add up to less than 1500 line, I saw a few times over and over again, in fact, many places are not very clear to see here just feel I can be of use where listed.
Use CustomNSError agreement
In fact, this agreement is inherited from Error protocol, note that this agreement CustomNSError more conducive to using the Error conducted as NSError.
SwiftJSON source code as follows
public enum SwiftyJSONError: Int, Swift.Error {
case unsupportedType = 999
case indexOutOfBounds = 900
case elementTooDeep = 902
case wrongType = 901
case notExist = 500
case invalidJSON = 490
}
extension SwiftyJSONError: CustomNSError {
/// return the error domain of SwiftyJSONError
public static var errorDomain: String { return "com.swiftyjson.SwiftyJSON" }
/// return the error code of SwiftyJSONError
public var errorCode: Int { return self.rawValue }
/// return the userInfo of SwiftyJSONError
public var errorUserInfo: [String: Any] {
switch self {
case .unsupportedType:
return [NSLocalizedDescriptionKey: "It is an unsupported type."]
case .indexOutOfBounds:
return [NSLocalizedDescriptionKey: "Array Index is out of bounds."]
case .wrongType:
return [NSLocalizedDescriptionKey: "Couldn't merge, because the JSONs differ in type on top level."]
case .notExist:
return [NSLocalizedDescriptionKey: "Dictionary key does not exist."]
case .invalidJSON:
return [NSLocalizedDescriptionKey: "JSON is invalid."]
case .elementTooDeep:
return [NSLocalizedDescriptionKey: "Element too deep. Increase maxObjectDepth and make sure there is no reference loop."]
}
}
}
It is worth noting that this enumeration type must be defined, and preferably Int type. CustomNSError because compliance with the agreement, the property must be returned errorCode, this time usually enumeration of rawValue, enumeration defined as Int, then can be used seamlessly
To replace as usage by switch
Generally when there are objects we need to convert the type of use so I usually use
func toNSURL(url: Any) -> NSURL? {
if url is NSURL {
return url as? NSURL
}
if url is URL {
return (url as! URL) as NSURL
}
if url is String {
return NSURL(string: (url as! String))
}
return nil
}
In fact, this can be handled entirely by switch
func asNSURL(any: Any) -> NSURL? {
switch any {
case let nsURL as NSURL:
return nsURL
case let url as URL:
return url as NSURL
case let string as String:
return NSURL(string: string)
default:
return nil
}
}
Less unpack exclamation point less and less trouble
Source source, wherein there further comprises a recursive call to the map function, and in many SwiftJSON carried out by using:
private func unwrap(_ object: Any) -> Any {
switch object {
case let json as JSON:
return unwrap(json.object)
case let array as [Any]:
return array.map(unwrap)
case let dictionary as [String: Any]:
var unwrappedDic = dictionary
for (k, v) in dictionary {
unwrappedDic[k] = unwrap(v)
}
return unwrappedDic
default:
return object
}
}
NSNumber comparison process
The source process in more detail, a copy can be used in its own category, because this classification SwiftJSON is internal, so basically do not worry about a conflict copy
private let trueNumber = NSNumber(value: true)
private let falseNumber = NSNumber(value: false)
private let trueObjCType = String(cString: trueNumber.objCType)
private let falseObjCType = String(cString: falseNumber.objCType)
// MARK: - NSNumber: Comparable
extension NSNumber {
fileprivate var isBool: Bool {
let objCType = String(cString: self.objCType)
if (self.compare(trueNumber) == .orderedSame && objCType == trueObjCType) || (self.compare(falseNumber) == .orderedSame && objCType == falseObjCType) {
return true
} else {
return false
}
}
}
func == (lhs: NSNumber, rhs: NSNumber) -> Bool {
switch (lhs.isBool, rhs.isBool) {
case (false, true):
return false
case (true, false):
return false
default:
return lhs.compare(rhs) == .orderedSame
}
}
func != (lhs: NSNumber, rhs: NSNumber) -> Bool {
return !(lhs == rhs)
}
func < (lhs: NSNumber, rhs: NSNumber) -> Bool {
switch (lhs.isBool, rhs.isBool) {
case (false, true):
return false
case (true, false):
return false
default:
return lhs.compare(rhs) == .orderedAscending
}
}
func > (lhs: NSNumber, rhs: NSNumber) -> Bool {
switch (lhs.isBool, rhs.isBool) {
case (false, true):
return false
case (true, false):
return false
default:
return lhs.compare(rhs) == ComparisonResult.orderedDescending
}
}
func <= (lhs: NSNumber, rhs: NSNumber) -> Bool {
switch (lhs.isBool, rhs.isBool) {
case (false, true):
return false
case (true, false):
return false
default:
return lhs.compare(rhs) != .orderedDescending
}
}
func >= (lhs: NSNumber, rhs: NSNumber) -> Bool {
switch (lhs.isBool, rhs.isBool) {
case (false, true):
return false
case (true, false):
return false
default:
return lhs.compare(rhs) != .orderedAscending
}
}
Reproduced in: https: //www.jianshu.com/p/06f559f9e518