SwiftJSON source learning summary

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

Guess you like

Origin blog.csdn.net/weixin_34375233/article/details/91270572