泛型及其在網(wǎng)絡(luò)請求中的應(yīng)用

泛型(generic)可以使我們在程序代碼中定義一些可變的部分县爬,在運(yùn)行的時候指定耳高。使用泛型可以最大限度地重用代碼陆蟆、保護(hù)類型的安全以及提高性能。

舉個栗子:
要比較兩個Int值是否相等缕题,寫了下面這個函數(shù)

func compareIntValue(_ a: Int, b: Int) -> Bool {
     return a == b
}

要比較兩個Double值是否相等墅诡,修改一下上面的函數(shù)

func compareDoubleValue(_ a: Double, b: Double) -> Bool {
     return a == b
}

如果再想有一個比較字符串是否相等的函數(shù)呢酵使,我們不禁要想有沒有一個函數(shù)實現(xiàn)多種比較呢悦穿?

泛型函數(shù)

指定一個或多個類型占位符栗柒,類型暫時不確定逛钻,等具體調(diào)用的時候再確定

func compareValue<T: Comparable>(_ a: T, b: T) -> Bool {
     return a == b
}

現(xiàn)在我們可以用它來比較字符串了

let result = compareValue("123", b: "456")

是不是很方便,減少了重復(fù)代碼的書寫,更加靈活淋纲。

網(wǎng)絡(luò)請求

提到APP開發(fā),網(wǎng)絡(luò)請求是必不可少的一部分放祟。發(fā)起網(wǎng)絡(luò)請求鳍怨,將返回數(shù)據(jù)封裝成Model,交給Controller最終顯示在相應(yīng)的View上跪妥,MVC的開發(fā)模式基本如此鞋喇。下面是使用泛型優(yōu)化網(wǎng)絡(luò)請求的一次嘗試,先看看原來的網(wǎng)絡(luò)請求:

    //原網(wǎng)絡(luò)請求
    static func postNormalUrl(_ url: String, params: [String: String]?, completion: @escaping (_ data: Any?, _ error: Error?) -> ()) {
        let requestUrl = BaseUrl + url
        Alamofire.request(requestUrl, method: .post, parameters: params, encoding: URLEncoding.default, headers: nil).responseJSON { (response) in
            if response.result.isSuccess {
                completion(response.result.value, nil)
            } else {
                completion(nil, response.result.error)
            }
        }
    }
    //發(fā)起網(wǎng)絡(luò)請求
    NetworkManager.postNormalUrl("topic/info/58f821feee07cf0007f3bafb", params: params) { (data, error) in
            if let getData = data {
                let json = JSON(getData)
                let status = json["status"].intValue
                if status == 1 {
                    //封裝model
                } else {
                    print(json["msg"].stringValue)
                }
            } else {
                print(error!)
            }
     }

上面的請求只是進(jìn)行了簡單的封裝眉撵,網(wǎng)絡(luò)請求成功返回數(shù)據(jù)侦香,失敗返回error,在回調(diào)中判斷并進(jìn)行處理执桌,不難看出存在以下問題:
???1鄙皇、if判斷每個請求里面都要寫,存在大量重復(fù)代碼仰挣;
???2伴逸、status和msg沒有進(jìn)行封裝,需要通過key-value進(jìn)行取值膘壶;
???3错蝴、有沒有可能直接返回封裝好的model洲愤;

了解問題之后,我們嘗試進(jìn)行改造:
首先聲明一個BaseModel顷锰,包含兩個屬性status和msg柬赐,在這里使用了SwiftyJSON和ObjectMapper分別進(jìn)行映射,選擇適合自己的就好官紫;

import UIKit
import SwiftyJSON
import ObjectMapper

class BaseModel: Mappable {
    var status: Int?
    var msg: String?
    
    required init?(map: Map) {
        
    }
    
    func mapping(map: Map) {
        status  <- map["status"]
        msg     <- map["msg"]
    }
    
//    required init(json: JSON) {
//        status = json["status"].int
//        msg = json["msg"].string
//    }
}

看一下修改之后的網(wǎng)絡(luò)請求肛宋,使用到了泛型,傳入BaseModel類或其子類束世,成功后就會返回對應(yīng)的model;

static func postUrl<T: BaseModel>(_ url: String, params: [String: String]?, success: @escaping (_ model: T?) -> (), failure: @escaping (_ msg: String?) -> (), error: @escaping (_ error: Error?) -> ()) {
        let requestUrl = BaseUrl + url
        Alamofire.request(requestUrl, method: .post, parameters: params, encoding: URLEncoding.default, headers: nil).responseJSON { (response) in
            if response.result.isSuccess {
                if let getData = response.result.value {
//                    let json = JSON(getData)
//                    let model = T(json: json)
                    let getModel = Mapper<T>().map(JSONObject: getData)
                    if getModel?.status == 1 {
                        success(getModel)
                    } else {
                        failure(getModel?.msg)
                    }
                }
            } else {
                error(response.result.error)
            }
        }
    }
NetworkManager.postUrl("topic/info/58f821feee07cf0007f3bafb", params: params, success: { (model: BaseModel?) in
            print(model?.msg)
        }, failure: { (msg) in
            print(msg)
        }) { (error) in
            print(error)
        }

通過改造解決了上面存在的問題:
???1酝陈、對各種狀態(tài)只會在一處進(jìn)行判斷,減少了重復(fù)代碼毁涉;
???2沉帮、將status和msg放入了BaseModel中;
???3贫堰、直接返回對應(yīng)的Model穆壕,可在回調(diào)中直接使用;
對于第三條可能上面的例子不是很明顯其屏,再創(chuàng)建一個Model繼承自BaseModel喇勋;

import UIKit
import SwiftyJSON
import ObjectMapper

//class TestModel: BaseModel {
//    var contentStr: String?
//    var replyArray: [ReplyModel]?
//    var recommendArray: [RecommendModel]?
//    
//    required init(json: JSON) {
//        super.init(json: json)
//        if status == 1 {
//            let data = json["data"].dictionaryValue
//            contentStr = data["content"]?.string
//            let replies = data["replies"]?.array
//            let recommend = data["recommend"]?.array
//            if let reply = replies {
//                if reply.count > 0 {
//                    replyArray = [ReplyModel]()
//                    for data in reply {
//                        let replyModel = ReplyModel(json: data)
//                        replyArray?.append(replyModel)
//                    }
//                }
//            }
//            if let recom = recommend {
//                if recom.count > 0 {
//                    
//                }
//            }
//        }
//    }
//}

class TestModel: BaseModel {
    var contentStr: String?
    
    required init?(map: Map) {
        super.init(map: map)
    }
    
    override func mapping(map: Map) {
        status  <- map["status"]
        msg     <- map["msg"]
        contentStr <- map["data.content"]
    }
}
NetworkManager.postUrl("topic/info/58f821feee07cf0007f3bafb", params: params, success: { (testModel: TestModel?) in
            print(testModel?.contentStr)
        }, failure: { (msg) in
            print(msg)
        }) { (error) in
            print(error)
        }

在上面的例子中,通過泛型傳入的實際類型是TestModel漫玄,在回調(diào)中直接獲取到了TestModel對象茄蚯,可以直接拿來用,是不是很方便睦优。

Demo鏈接

OC版本的沒有具體實現(xiàn),可以看這篇文章文章鏈接
參考鏈接
Swift泛型和泛型函數(shù)
Swift學(xué)習(xí)之泛型

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末壮不,一起剝皮案震驚了整個濱河市汗盘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌询一,老刑警劉巖隐孽,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異健蕊,居然都是意外死亡菱阵,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進(jìn)店門缩功,熙熙樓的掌柜王于貴愁眉苦臉地迎上來晴及,“玉大人,你說我怎么就攤上這事嫡锌÷羌冢” “怎么了琳钉?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蛛倦。 經(jīng)常有香客問我歌懒,道長,這世上最難降的妖魔是什么溯壶? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任及皂,我火速辦了婚禮,結(jié)果婚禮上且改,老公的妹妹穿的比我還像新娘躲庄。我一直安慰自己,他們只是感情好钾虐,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布噪窘。 她就那樣靜靜地躺著,像睡著了一般效扫。 火紅的嫁衣襯著肌膚如雪倔监。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天菌仁,我揣著相機(jī)與錄音浩习,去河邊找鬼。 笑死济丘,一個胖子當(dāng)著我的面吹牛谱秽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播摹迷,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼疟赊,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了峡碉?” 一聲冷哼從身側(cè)響起近哟,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鲫寄,沒想到半個月后吉执,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡地来,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年戳玫,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片未斑。...
    茶點(diǎn)故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡咕宿,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情荠列,我是刑警寧澤类浪,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站肌似,受9級特大地震影響费就,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜川队,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一力细、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧固额,春花似錦眠蚂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至啄糙,卻和暖如春笛臣,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背隧饼。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工沈堡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人燕雁。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓诞丽,卻偏偏與公主長得像,于是被迫代替她去往敵國和親拐格。 傳聞我的和親對象是個殘疾皇子僧免,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評論 2 359

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