網(wǎng)絡(luò)抽象層庫Moya的基本使用

一凄诞、基本介紹

1. 什么是 Moya

(1)我們知道在 iOS 開發(fā)中,可以使用 URLSession 進行網(wǎng)絡(luò)請求泼差。但為了方便起見椭盏,我通常會選擇使用 Alamofire 這樣的第三方庫。這些庫本質(zhì)上也是基于 URLSession 的,但其封裝了許多細節(jié)利职,可以讓我們網(wǎng)絡(luò)請求相關(guān)代碼(如獲取數(shù)據(jù)趣效,提交數(shù)據(jù),上傳文件猪贪,下載文件等)更加簡潔易用跷敬。

(2)而 Moya 又是一個基于 Alamofire 的更高層網(wǎng)絡(luò)請求封裝抽象層。Moya 也就可以看做我們的網(wǎng)絡(luò)管理層热押,用來封裝 URL西傀、參數(shù)等請求所需要的一些基本信息。使用后我們的客戶端代碼會直接操作 Moya桶癣,然后 Moya 去管理請求拥褂,而不用跟 Alamofire 進行直接接觸。

2牙寞,使用 Moya 的優(yōu)點

(1)在我們項目的 Service饺鹃、View、或者 Model 文件中可能都會出現(xiàn)請求網(wǎng)絡(luò)數(shù)據(jù)的情況间雀,如果直接使用 Alamofire悔详,不僅很繁瑣,而且還會使代碼變得很混亂惹挟。

(2)過去我們通常的做法是在項目中添加一個網(wǎng)絡(luò)請求層(比如叫做 APIManager茄螃、或者 NetworkModel),用來管理網(wǎng)絡(luò)請求匪煌。但這樣做可能會遇到一些問題:

  • 難以開發(fā)一個新的 App(不知從哪里下手)
  • 難以維護現(xiàn)有的 App(這一層比較混亂责蝠,混合了各種請求不好管理。)
  • 難以做做單元測試


    image.png

二萎庭、安裝配置

由于 Moya 需要依賴 Alamofire 庫霜医,手動配置會麻煩些。所以下面我們還是使用 CocoaPods 來進行安裝配置驳规。

1肴敛,創(chuàng)建 Podfile

首先進入到工程的根目錄下,創(chuàng)建空白的 Podfile 文件吗购。

cd /Users/hangge/Documents/Code/hangge_1797
touch Podfile
2医男,編輯 Podfile

我們在 Podfile 文件中寫上需要引入的第三方庫:Alamofire、Moya捻勉、SwiftyJSON(方便解析返回的 JSON 數(shù)據(jù))

use_frameworks!
 
def libraries
  pod 'Alamofire'
  pod 'Moya'
  pod 'SwiftyJSON'
end
 
target 'hangge_1797' do
  platform :ios, '8.0'
  libraries
end
3镀梭,開始導(dǎo)入庫

執(zhí)行下面命令,開始導(dǎo)入前面配置的第三方庫踱启。

cd /Users/hangge/Documents/Code/hangge_1358
pod install
4报账,打開新生成的 .xcworkspace 文件

往后我們就需要使用這個新生成的 hangge_1797.xcworkspace 文件來開發(fā)研底。因為原來的工程(hangge_1358.xcodeproj)設(shè)置已經(jīng)被更改了,如果我們直接打開原來的工程文件去編譯就會報錯透罢。


image.png

三榜晦、使用樣例

1,效果圖

(1)我們使用 Moya 調(diào)用豆瓣 FM 的 API 接口羽圃,獲取所有的頻道列表并顯示在表格中乾胶。

(2)點擊任意一個頻道,調(diào)用另一個接口隨機獲取該頻道下的一首歌曲朽寞,并彈出顯示识窿。

image.png

image.png
2,樣例代碼

(1)DouBanAPI.swift(網(wǎng)絡(luò)請求層)

  • 首先我們定義一個 provider愁憔,即請求發(fā)起對象腕扶。往后我們?nèi)绻l(fā)起網(wǎng)絡(luò)請求就使用這個 provider。
  • 接著聲明一個 enum 來對請求進行明確分類吨掌,這里我們定義兩個枚舉值分別表示獲取頻道列表半抱、獲取歌曲信息。
  • 最后讓這個 enum 實現(xiàn) TargetType 協(xié)議膜宋,在這里面定義我們各個請求的 url窿侈、參數(shù)、header 等信息秋茫。
import Foundation
import Moya
 
//初始化豆瓣FM請求的provider
let DouBanProvider = MoyaProvider<DouBan>()
 
/** 下面定義豆瓣FM請求的endpoints(供provider使用)**/
 
//請求分類
public enum DouBan {
    case channels  //獲取頻道列表
    case playlist(String) //獲取歌曲
}
 
//請求配置
extension DouBan: TargetType {
    //服務(wù)器地址
    public var baseURL: URL {
        switch self {
        case .channels:
            return URL(string: "https://www.douban.com")!
        case .playlist(_):
            return URL(string: "https://douban.fm")!
        }
    }
     
    //各個請求的具體路徑
    public var path: String {
        switch self {
        case .channels:
            return "/j/app/radio/channels"
        case .playlist(_):
            return "/j/mine/playlist"
        }
    }
     
    //請求類型
    public var method: Moya.Method {
        return .get
    }
     
    //請求任務(wù)事件(這里附帶上參數(shù))
    public var task: Task {
        switch self {
        case .playlist(let channel):
            var params: [String: Any] = [:]
            params["channel"] = channel
            params["type"] = "n"
            params["from"] = "mainsite"
            return .requestParameters(parameters: params,
                                      encoding: URLEncoding.default)
        default:
            return .requestPlain
        }
    }
     
    //是否執(zhí)行Alamofire驗證
    public var validate: Bool {
        return false
    }
     
    //這個就是做單元測試模擬的數(shù)據(jù)史简,只會在單元測試文件中有作用
    public var sampleData: Data {
        return "{}".data(using: String.Encoding.utf8)!
    }
     
    //請求頭
    public var headers: [String: String]? {
        return nil
    }
}

(2)ViewController.swift(主視圖代碼)
代碼中高亮部分是通過 Moya 發(fā)起網(wǎng)絡(luò)請求「刂可以看到頁面上不再有 url 地址圆兵、參數(shù)拼接、請求方式等枢贿,比直接使用 Alamofire 清爽許多殉农。

import UIKit
import SwiftyJSON
 
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
     
    //顯示頻道列表的tableView
    var tableView:UITableView!
     
    //頻道列表數(shù)據(jù)
    var channels:Array<JSON> = []
     
    override func viewDidLoad() {
        super.viewDidLoad()
         
        //創(chuàng)建表視圖
        self.tableView = UITableView(frame:self.view.frame, style:.plain)
        self.tableView!.delegate = self
        self.tableView!.dataSource = self
        //創(chuàng)建一個重用的單元格
        self.tableView!.register(UITableViewCell.self,
                                 forCellReuseIdentifier: "SwiftCell")
        self.view.addSubview(self.tableView!)
         
        //使用我們的provider進行網(wǎng)絡(luò)請求(獲取頻道列表數(shù)據(jù))
        DouBanProvider.request(.channels) { result in
            if case let .success(response) = result {
                //解析數(shù)據(jù)
                let data = try? response.mapJSON()
                let json = JSON(data!)
                self.channels = json["channels"].arrayValue
                 
                //刷新表格數(shù)據(jù)
                DispatchQueue.main.async{
                    self.tableView.reloadData()
                }
            }
        }
    }
     
    //返回表格分區(qū)數(shù)
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
     
    //返回表格行數(shù)(也就是返回控件數(shù))
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return channels.count
    }
     
    //創(chuàng)建各單元顯示內(nèi)容(創(chuàng)建參數(shù)indexPath指定的單元)
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
        -> UITableViewCell {
            //為了提供表格顯示性能,已創(chuàng)建完成的單元需重復(fù)使用
            let identify:String = "SwiftCell"
            let cell = tableView.dequeueReusableCell(
                withIdentifier: identify, for: indexPath)
            cell.accessoryType = .disclosureIndicator
            //設(shè)置單元格內(nèi)容
            cell.textLabel?.text = channels[indexPath.row]["name"].stringValue
            return cell
    }
     
    //處理列表項的選中事件
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        //獲取選中項信息
        let channelName = channels[indexPath.row]["name"].stringValue
        let channelId = channels[indexPath.row]["channel_id"].stringValue
         
        //使用我們的provider進行網(wǎng)絡(luò)請求(根據(jù)頻道ID獲取下面的歌曲)
        DouBanProvider.request(.playlist(channelId)) { result in
            if case let .success(response) = result {
                //解析數(shù)據(jù)局荚,獲取歌曲信息
                let data = try? response.mapJSON()
                let json = JSON(data!)
                let music = json["song"].arrayValue[0]
                let artist = music["artist"].stringValue
                let title = music["title"].stringValue
                let message = "歌手:\(artist)\n歌曲:\(title)"
                 
                //將歌曲信息彈出顯示
                self.showAlert(title: channelName, message: message)
            }
        }
    }
     
    //顯示消息
    func showAlert(title:String, message:String){
        let alertController = UIAlertController(title: title,
                                                message: message, preferredStyle: .alert)
        let cancelAction = UIAlertAction(title: "確定", style: .cancel, handler: nil)
        alertController.addAction(cancelAction)
        self.present(alertController, animated: true, completion: nil)
    }
     
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末超凳,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子耀态,更是在濱河造成了極大的恐慌轮傍,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件首装,死亡現(xiàn)場離奇詭異创夜,居然都是意外死亡,警方通過查閱死者的電腦和手機仙逻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門挥下,熙熙樓的掌柜王于貴愁眉苦臉地迎上來揍魂,“玉大人,你說我怎么就攤上這事棚瘟。” “怎么了喜最?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵偎蘸,是天一觀的道長。 經(jīng)常有香客問我瞬内,道長迷雪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任虫蝶,我火速辦了婚禮章咧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘能真。我一直安慰自己赁严,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布粉铐。 她就那樣靜靜地躺著疼约,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蝙泼。 梳的紋絲不亂的頭發(fā)上程剥,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機與錄音汤踏,去河邊找鬼织鲸。 笑死,一個胖子當(dāng)著我的面吹牛溪胶,可吹牛的內(nèi)容都是我干的搂擦。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼载荔,長吁一口氣:“原來是場噩夢啊……” “哼盾饮!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起懒熙,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤丘损,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后工扎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體徘钥,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年肢娘,在試婚紗的時候發(fā)現(xiàn)自己被綠了呈础。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舆驶。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖而钞,靈堂內(nèi)的尸體忽然破棺而出沙廉,到底是詐尸還是另有隱情,我是刑警寧澤臼节,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布撬陵,位于F島的核電站,受9級特大地震影響网缝,放射性物質(zhì)發(fā)生泄漏巨税。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一粉臊、第九天 我趴在偏房一處隱蔽的房頂上張望草添。 院中可真熱鬧,春花似錦扼仲、人聲如沸远寸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽而晒。三九已至,卻和暖如春阅畴,著一層夾襖步出監(jiān)牢的瞬間倡怎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工贱枣, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留监署,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓纽哥,卻偏偏與公主長得像钠乏,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子春塌,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355

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