淺談Swift網(wǎng)絡(luò)編程最佳實(shí)踐

序言

以Swift為iOS開(kāi)發(fā)入門(mén)語(yǔ)言的新手遣鼓,在網(wǎng)絡(luò)編程時(shí)往往容易存在以下兩個(gè)問(wèn)題:

  • 沒(méi)有網(wǎng)絡(luò)層,網(wǎng)絡(luò)請(qǐng)求的代碼散落在各處重贺,難以統(tǒng)一管理骑祟,難以維護(hù)。
  • 根據(jù)JSON手寫(xiě)Model气笙,采用SwiftyJSON這種半自動(dòng)的方式進(jìn)行JSON解析次企,再手工將經(jīng)SwiftyJSON處理的半成品數(shù)據(jù)灌入Model之中,效率極其低下潜圃,代碼冗余繁雜缸棵。

首先我會(huì)提出一個(gè)網(wǎng)絡(luò)層設(shè)計(jì)方案,之后是一個(gè)基于該設(shè)計(jì)的完整Swift網(wǎng)絡(luò)編程實(shí)踐秉犹。

沒(méi)耐心看漁的可以直接看最后的魚(yú)蛉谜。

網(wǎng)絡(luò)層設(shè)計(jì)

在設(shè)計(jì)之前,我參考了@反革命攻城獅iOS應(yīng)用架構(gòu)談 網(wǎng)絡(luò)層設(shè)計(jì)方案

他設(shè)計(jì)的網(wǎng)絡(luò)層包括兩部分: Manager 和 Reformer崇堵。

每個(gè)業(yè)務(wù)層擁有自己的Manager實(shí)例和Reformer實(shí)例型诚,Manager實(shí)例負(fù)責(zé)發(fā)送請(qǐng)求,取得JSON數(shù)據(jù)鸳劳,JSON經(jīng)Reformer處理后狰贯,采用Delegate的方式通知調(diào)用的業(yè)務(wù)層。

我的設(shè)計(jì)只包含Manager赏廓,而且各個(gè)業(yè)務(wù)層不擁有自己的Manager實(shí)例涵紊,Manager類本身提供一個(gè)單例,單例的實(shí)例方法是對(duì)各個(gè)API的調(diào)用幔摸,每個(gè)方法對(duì)應(yīng)一個(gè)API摸柄,業(yè)務(wù)層將completionHandler傳給Manager單例的相應(yīng)方法,該方法發(fā)出網(wǎng)絡(luò)請(qǐng)求既忆,并對(duì)得到的JSON進(jìn)行解析驱负,將解析完得到的Model傳回業(yè)務(wù)層嗦玖。

設(shè)計(jì)上,我把他講的回調(diào)時(shí)不用block跃脊,不要在Manager內(nèi)解析JSON這兩條都違背了..宇挫,關(guān)于回調(diào)時(shí)用不用block,因?yàn)槲也捎玫氖菃卫沂酰椅也幌雽SON解析下放給業(yè)務(wù)層器瘪,如果硬要采用Delegate,那我就不得不為每個(gè)業(yè)務(wù)層提供一個(gè)專門(mén)的Delegate來(lái)為其進(jìn)行JSON解析绘雁,如果有N個(gè)業(yè)務(wù)層橡疼,我需要先定義N個(gè)Protocol,再為Manager增加N個(gè)變量咧七,同時(shí)還需要使N個(gè)業(yè)務(wù)層接受單例的委托衰齐,這是不現(xiàn)實(shí)的,如果采用block继阻,所需要做的就只是在相應(yīng)方法內(nèi)為該block添加上JSON解析的代碼然后傳給Alamofire就可以了。關(guān)于為什么在Manager內(nèi)解析JSON了废酷,我覺(jué)得這一行代碼的問(wèn)題.. 就不用給業(yè)務(wù)層了吧瘟檩。

最佳實(shí)踐嘗試

OC傳統(tǒng)的JSON解析方式是利用插件或其他工具依照J(rèn)SON生成Model的代碼,然后將得到的JSON利用YYModel或MJExtension之類的第三方庫(kù)一行注入到Model中澈蟆,的確比文章開(kāi)頭提到的方法簡(jiǎn)單多了墨辛,但雖然MJExtension這類的第三方庫(kù)支持Swift,但我在嘗試使用的時(shí)候遇到了NSArray和Array不兼容的問(wèn)題趴俘,可能是我的配置有問(wèn)題睹簇,但我找到了其他可以替代而且更簡(jiǎn)單的方式,就是用JSONExport寥闪。

JSONExport可以根據(jù)JSON為你生成對(duì)應(yīng)的Model代碼太惠,并且也迭代的幫你寫(xiě)好了JSON轉(zhuǎn)Model的代碼,即Model的 formDictionary 方法疲憋。

魚(yú)

第一步:https://github.com/Ahmed-Ali/JSONExport 下一個(gè)JSONExport

第二步:將JSON復(fù)制進(jìn)去

JSONExport

得到三個(gè)Model文件凿渊,拖進(jìn)你的工程,選中copyIfNeeded

第三步:依照之前的網(wǎng)絡(luò)層設(shè)計(jì)缚柳,建一個(gè)Manager埃脏,提供一個(gè)單例,并為每個(gè)API寫(xiě)一個(gè)接受完成閉包的方法秋忙。

class NetworkingManager {
    static let sharedInstance = NetworkingManager()
    
    func requestDataForMainPage(completionHandler: (mainPage: FirstPage?) -> Void) {
        
    }
}

第四步:使用Alamofire發(fā)送網(wǎng)絡(luò)請(qǐng)求彩掐,在完成閉包里使用 JSONExport 為每個(gè)Model提供的fromDictionary方法將JSON灌進(jìn)Model中,將Model傳給業(yè)務(wù)層送來(lái)的completionHandler灰追。

class NetworkingManager {
    static let sharedInstance = NetworkingManager()
    
    func requestDataForMainPage(completionHandler: (mainPage: FirstPage?) -> Void) {
        Alamofire.request(.GET, "http://news-at.zhihu.com/api/4/news/latest").responseJSON(options: .AllowFragments) { response in
            guard let json = response.result.value else {
                print("Error occur")
                completionHandler(mainPage: nil)
                return
            }
            
            let model = FirstPage(fromDictionary: json as! NSDictionary)
            completionHandler(mainPage: model)
        }
    }

第五步:業(yè)務(wù)層的代碼通過(guò)調(diào)用單例的對(duì)應(yīng)函數(shù)訪問(wèn)相應(yīng)API堵幽,并直接獲得該API所對(duì)應(yīng)的Model狗超。

NetworkingManager.sharedInstance.requestDataForMainPage { (mainPage) in
            if let exist = mainPage {
                self.mainPage = exist
                print("something")
            } else {
                print("nothing")
            }
        }

這樣既實(shí)現(xiàn)了網(wǎng)絡(luò)訪問(wèn)的統(tǒng)一管理又避免了大段的JSON解析代碼,比起原來(lái)的方法谐檀,不知道高到哪里去了抡谐。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市桐猬,隨后出現(xiàn)的幾起案子麦撵,更是在濱河造成了極大的恐慌,老刑警劉巖溃肪,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件免胃,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡惫撰,警方通過(guò)查閱死者的電腦和手機(jī)羔沙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)厨钻,“玉大人扼雏,你說(shuō)我怎么就攤上這事『话颍” “怎么了诗充?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)诱建。 經(jīng)常有香客問(wèn)我蝴蜓,道長(zhǎng),這世上最難降的妖魔是什么俺猿? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任茎匠,我火速辦了婚禮,結(jié)果婚禮上押袍,老公的妹妹穿的比我還像新娘诵冒。我一直安慰自己,他們只是感情好伯病,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布造烁。 她就那樣靜靜地躺著,像睡著了一般午笛。 火紅的嫁衣襯著肌膚如雪惭蟋。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,488評(píng)論 1 302
  • 那天药磺,我揣著相機(jī)與錄音告组,去河邊找鬼。 笑死癌佩,一個(gè)胖子當(dāng)著我的面吹牛木缝,可吹牛的內(nèi)容都是我干的便锨。 我是一名探鬼主播,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼我碟,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼放案!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起矫俺,我...
    開(kāi)封第一講書(shū)人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤吱殉,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后厘托,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體友雳,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年铅匹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了押赊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡包斑,死狀恐怖流礁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情罗丰,我是刑警寧澤崇棠,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站丸卷,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏询刹。R本人自食惡果不足惜谜嫉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望凹联。 院中可真熱鬧沐兰,春花似錦、人聲如沸蔽挠。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)澳淑。三九已至比原,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間杠巡,已是汗流浹背量窘。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留氢拥,地道東北人蚌铜。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓锨侯,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親冬殃。 傳聞我的和親對(duì)象是個(gè)殘疾皇子囚痴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容