日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > javascript >内容正文

javascript

SwiftyJSON源码分析

發(fā)布時(shí)間:2023/12/14 javascript 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SwiftyJSON源码分析 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

SwiftyJSON是iOS Swift語(yǔ)言JSON解析的三方庫(kù),主要是基于對(duì)iOS原生JSONSerialization類的封裝, 最新的版本是3.4.1,它只有一個(gè)swift文件。?

json庫(kù)和http庫(kù)是哥倆分不開的, Swift語(yǔ)言的http交互可以用Alamofire;還有個(gè)Alamofire-SwiftyJSON, 看名字就知道它是使用在Alamofire庫(kù)里的JSON解析, 但它依然不支持json和model轉(zhuǎn)換(感覺比Java的fastjson和Gson庫(kù)low了幾條街,Xcode也不支持類似于Android Studio的GsonFormat插件。。。)。

我覺得做項(xiàng)目時(shí)應(yīng)該用不到SwiftyJSON, 因?yàn)樗恢С謏son和Model的互轉(zhuǎn), 阿里巴巴的HandyJson更貼近于實(shí)戰(zhàn)。

分析SwiftyJSON代碼主要是為了學(xué)習(xí)Swift語(yǔ)言的語(yǔ)法和技巧。 下面先總結(jié)一下有用的語(yǔ)法:
1、支持的數(shù)據(jù)類型, 使用枚舉定義(考慮一下各自的rawValue是多少?):?

public enum Type :Int{
case number
case string
case bool
case array
case dictionary
case null
case unknown
}

2、SwiftyJSON暴露出的JSON是結(jié)構(gòu)體,考慮一下為什么不是類? 因?yàn)榻Y(jié)構(gòu)體是值拷貝, 即傳參時(shí)會(huì)新創(chuàng)建一份拷貝。

// MARK: - JSON Base
public struct JSON {
...
}

3、泛型的用法, 其中Comparable是協(xié)議類型, 在Java里稱作接口類。

public enum Index<T: Any>: Comparable 這條語(yǔ)句的意思是泛型T繼承于Any, 可以是任何數(shù)據(jù)類型。等價(jià)于 public enum Index<T>: Comparable 將Any改成AnyObject會(huì)怎樣? public enum Index<T: AnyObject>: Comparable 區(qū)別是AnyObject必須是類, 即枚舉使用的泛型T數(shù)據(jù)類型必須是類。
調(diào)用方法: public typealias JSONIndex = Index<JSON>
public typealias JSONRawIndex = Index<Any>

4、 Dictionary的聲明和構(gòu)造語(yǔ)法, 注意等號(hào)右邊是實(shí)例化; 還有N次循環(huán)的實(shí)現(xiàn)。

var data: [String: JSON] = [:]
(0...100000).forEach { n in //循環(huán)100001次,n等于[0,100000]
data["(n)"] = JSON([
"name": "item(n)",
"id": n
])
} 分析: (0...100000)的意思是創(chuàng)建一個(gè)Array實(shí)例,值是從0到100000, forEach是Array的實(shí)例方法。 $0和$1是第一個(gè)參數(shù)、第二個(gè)參數(shù), 用在[String:JSON]里$0是String,$1是JSON。

上面的循環(huán)還可以這樣寫, 還有個(gè)Swift特性就是數(shù)字支持下劃線分隔, 100000等價(jià)于100_000, 可讀性更好。

for n in 0...100_000 {
.... //n的值是從0到100000, 循環(huán)100001次
} 如果循環(huán)里用不到當(dāng)前次數(shù),可以用下劃線代替。 for _ in 0...100_000 {
...
}

5、 5種訪問(wèn)權(quán)限 open>public>internal>fileprivate>private, 同比Java的public>protected>private。 extension和subscript的用法都是基本使用方式,不多說(shuō)。

6、函數(shù)參數(shù)的默認(rèn)值, 規(guī)則是從后面的參數(shù)開始可以設(shè)置默認(rèn)值, 語(yǔ)法是等號(hào)和值。 例如下面函數(shù)有3個(gè)參數(shù), 第2和3個(gè)參數(shù)都有默認(rèn)值,在調(diào)用時(shí)只寫第一個(gè)參數(shù)也可以。 假如第2個(gè)參數(shù)有默認(rèn)值,第3個(gè)參數(shù)沒有默認(rèn)值是否可以呢? 答案是No, 如果當(dāng)前參數(shù)有默認(rèn)值,那么后面的參數(shù)必須有默認(rèn)值。

public init(data: Data, options opt: JSONSerialization.ReadingOptions = .allowFragments, error: NSErrorPointer = nil) 調(diào)用:let json = JSON(data:self.testData) //第2個(gè)參數(shù)是默認(rèn)值.allowFragments,第3個(gè)參數(shù)是nil。
下面說(shuō)說(shuō)JSON解析的實(shí)現(xiàn):
func testInitPerformance() {
self.measure() {
for _ in 1...100 {
print("begin")
print(String(data: self.testData, encoding: String.Encoding.utf8)!)
let json = JSON(data:self.testData)
print("resutl: (json[0]["text"])")
XCTAssertTrue(json != JSON.null)
}
}
}

SwiftyJSON源碼結(jié)構(gòu)如下圖所示:


屏幕快照 2017-01-14 下午3.53.08.png

以testInitPerformance函數(shù)為例說(shuō)明時(shí)序:
1、 let json = JSON(data: self.testData)會(huì)先執(zhí)行哪行代碼?
如果你說(shuō)就是執(zhí)行了上面提到的init構(gòu)造函數(shù), 那你就錯(cuò)了。
跟其它語(yǔ)言類似,如果結(jié)構(gòu)體/類/枚舉有成員變量時(shí), 首先按照代碼次序?qū)嵗蓡T變量; 然后才是構(gòu)造函數(shù); 這也是lazy關(guān)鍵字(即懶加載)存在的意義!


執(zhí)行的第一條語(yǔ)句.png

2、因?yàn)镾wiftyJSON是對(duì)JSONSerialization類的封裝,對(duì)于純文本數(shù)據(jù)JSON結(jié)構(gòu)體肯定要執(zhí)行JSONSerialization的方法。


反序列號(hào).png

3、 執(zhí)行self.init(jsonObject: object)會(huì)進(jìn)入下面的函數(shù), 看起來(lái)只有一句話, 但并不是這么簡(jiǎn)單哦!

fileprivate init(jsonObject: Any) {
self.object = jsonObject //會(huì)執(zhí)行object的set方法(觀察者模式)
}
賦值操作執(zhí)行了object變量的set方法, 作用是判斷數(shù)據(jù)類型。
public var object: Any {
get {
... //省略
}
set {error = nil
switch newValue {
case let number as NSNumber:
if number.isBool {
_type = .bool
self.rawBool = number.boolValue
} else {
_type = .number
self.rawNumber = number
}
case let string as String:
_type = .string
self.rawString = string
case
as NSNull:type = .null
case
as [JSON]:
_type = .array
case nil:
_type = .null
case let array as [Any]:
_type = .array
self.rawArray = array
case let dictionary as [String : Any]:
_type = .dictionary
self.rawDictionary = dictionary
default:
_type = .unknown
_error = NSError(domain: ErrorDomain, code: ErrorUnsupportedType, userInfo: [NSLocalizedDescriptionKey: "It is a unsupported type"])
}
}

JSON對(duì)象構(gòu)造過(guò)程到此結(jié)束!

下面看看是如何取值的, 以SwiftyJSON比較屌的特性多維取值為例:print("resutl: (json[0]["text"])")
PS: 看到方框應(yīng)該想到下標(biāo)語(yǔ)法,對(duì)應(yīng)subcript關(guān)鍵字(跟數(shù)組取值語(yǔ)法類似)。

1、 SwiftyJSON的官方結(jié)束里有這么一句let name = json[1]["list"][2]["name"].string, 參數(shù)可以任意長(zhǎng)度。 那么函數(shù)該怎么聲明參數(shù)呢? Swift使用了跟Java類似的...


若干個(gè)參數(shù).png

2、因?yàn)樵紨?shù)據(jù)是嵌套json格式,根據(jù)下標(biāo)參數(shù)類型, 代碼會(huì)執(zhí)行到JSON(o), 在這里是遞歸調(diào)用。


字符串.png

就分析這么多了, 如果想了解更多應(yīng)該分析一下HandyJSON源碼。


總結(jié)

以上是生活随笔為你收集整理的SwiftyJSON源码分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。