美文网首页swift
SwiftJSON源码学习小结

SwiftJSON源码学习小结

作者: seasonZhu | 来源:发表于2019-06-03 15:00 被阅读0次

其实SwiftJSON源码一共加起来也就不到1500行,我翻来覆去的看了几次,其实很多地方都是看得不是特别明白.这里只是将自己觉得可以加以利用的地方列出来.

CustomNSError协议的使用

其实这个协议是继承自协议Error的,需要注意的是这个协议CustomNSError更有利于将Error向NSError进行as使用.
SwiftJSON的源码如下

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."]
        }
    }
}

值得注意的是,这个枚举必须要定义类型,而且最好是Int类型.因为遵守CustomNSError协议,必须返回errorCode这个属性, 这个时候一般都是用枚举的rawValue,枚举定义为Int,那么就可以进行无缝的使用

通过switch 来替换 as用法

一般当有个对象我们需要转换类型的使用我一般是这么使用的

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
}

其实这个完全是可以通过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
    }
}

少一些解包少一些感叹号,少一些烦恼

源码出处,其中这里面还包含了在map函数的递归调用,并且SwiftJSON中多处这样进行了使用:

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的比较处理

这个源码处理的比较详细,完全可以copy一份在自己的分类中使用,因为这个分类在SwiftJSON是对内,所以基本上不用担心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
    }
}

相关文章

  • SwiftJSON源码学习小结

    其实SwiftJSON源码一共加起来也就不到1500行,我翻来覆去的看了几次,其实很多地方都是看得不是特别明白.这...

  • SwiftJSon源码阅读 --- 递归取值

    前言 SwiftJSon 可以说是Swift中比较好用的对JSon数据处理的第三方。心血来潮就阅读了一下源码,发现...

  • React源码学习小结

    正式开始系统地学习前端已经三个多月了,感觉前端知识体系庞杂但是又非常有趣。前端演进到现在对开发人员的代码功底要求已...

  • 2020-06-18

    GCD 源码 Git - rebase 用法小结 ReactNative源码解析——通信机制详解(1/2) Rea...

  • SwiftJson使用

    参考https://github.com/SwiftyJSON/SwiftyJSONhttp://tangplin...

  • SwiftJSON解读

    前言:SwiftJSON用起来是非常舒服的比如这种东西,再也不需要判断 ? !了 很舒服image.png 下面看...

  • Material之CoordinatorLayout + Beh

    最新项目中用到了些Material效果,在此对自己的学习做个小结。 首先养成良好的学习习惯-----看源码: Co...

  • Spring源码学习⑥-IOC小结

    IOC容器涉及的知识点: 1、组件添加 ①、@ComponetScan ②、@Bean ③、@Configur...

  • Spark源码分析小结

    Spark源码分析小结 通过前面对Master,worker,executor,sparkContext,DAGS...

  • Swift常用第三方框架搜集

    框架列表: 网络库: Alamofire JSON解析库: SwiftJSON JSON to Model:Obj...

网友评论

    本文标题:SwiftJSON源码学习小结

    本文链接:https://www.haomeiwen.com/subject/mlecxctx.html