SwiftJSON源码学习小结
2019-06-03 本文已影响0人
seasonZhu
其实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
}
}