翻遍百度沒事找到合適的參考文章,最終找到了這篇以圖片加載講解隊(duì)列的文章https://juejin.im/post/5b6047dae51d4517580e1627
問題:項(xiàng)目進(jìn)入首頁(yè)需要進(jìn)行多個(gè)多次的網(wǎng)絡(luò)請(qǐng)求,如果有一個(gè)請(qǐng)求失敗或者網(wǎng)絡(luò)問題仍然會(huì)請(qǐng)求其他接口。(非AFN,原生網(wǎng)絡(luò)請(qǐng)求方式)
思路:讓網(wǎng)絡(luò)請(qǐng)求以隊(duì)列的方式進(jìn)行,先進(jìn)先出,一個(gè)失敗取消剩余請(qǐng)求。
實(shí)現(xiàn):
1、保存請(qǐng)求的類
//請(qǐng)求狀態(tài)枚舉
enum RequestState {
case new,start,failed,success
}
//請(qǐng)求記錄
class LZUrlRecord {
let name: String
let url:String
var state = RequestState.new
var dicParamter:Dictionary<String,Any>?
var strParamter:String?
var completion:((RequestState,Dictionary<String,Any>)->())?
init(name:String,url:String){
self.name = name
self.url = url
}
}
2、隊(duì)列,及隊(duì)列中Operation實(shí)現(xiàn)
//保存隊(duì)列操作的單例
let sharePendingOperations = PendingOperations()
class PendingOperations{
//請(qǐng)求隊(duì)列
lazy var requestQueue:OperationQueue = {
var queue = OperationQueue()
queue.name = "Request queue"
queue.maxConcurrentOperationCount = 1
return queue
}()
//隊(duì)列掛起
func suspendAllOperations() {
self.requestQueue.isSuspended = true
}
// 隊(duì)列重啟
func resumeAllOperations() {
self.requestQueue.isSuspended = false
}
// 重置隊(duì)列
func resetAllOperations() {
self.requestQueue.cancelAllOperations()
self.resumeAllOperations()
}
}
//Operation是一個(gè)抽象類,專為子類化而設(shè)計(jì)。每個(gè)子類代表一個(gè)特定的任務(wù),如前面的圖所示。
//自定義請(qǐng)求任務(wù)
class LZRequestTask: Operation {
let urlRecord:LZUrlRecord
init(_ urlRecord:LZUrlRecord){
self.urlRecord = urlRecord
}
override func main() {
//每次啟動(dòng)一個(gè)operation時(shí)將整個(gè)隊(duì)列掛起,暫停所有operations
sharePendingOperations.suspendAllOperations()
//發(fā)起網(wǎng)絡(luò)請(qǐng)求
RNetUtil.shareManager.requestTPOST(url: urlRecord.url, paramter: urlRecord.strParamter!) { (state, data) in
//有回調(diào)將網(wǎng)絡(luò)狀態(tài)及請(qǐng)求結(jié)果返回
if let handler = self.urlRecord.completion{
self.urlRecord.state = state
handler(state, data)
}
}
}
}
3、網(wǎng)絡(luò)請(qǐng)求
//網(wǎng)絡(luò)請(qǐng)求
func requestPOSTWithQueue(url:String,
paramter:String,
completion:@escaping ((RequestState,Dictionary<String,Any>)->Void)) {
//定義請(qǐng)求記錄實(shí)例
let urlRecord = LZUrlRecord.init(name: url, url: url)
urlRecord.strParamter = paramter
// 實(shí)現(xiàn)回調(diào)
urlRecord.completion = {
(state,data) in
if state == .success{
// 成功時(shí)重新啟動(dòng)操作隊(duì)列
sharePendingOperations.resumeAllOperations()
}else{
// 失敗時(shí)重置操作隊(duì)列
sharePendingOperations.resetAllOperations()
}
//將網(wǎng)絡(luò)狀態(tài)和返回值傳回主線程刷新ui
completion(state,data)
}
// 網(wǎng)絡(luò)請(qǐng)求任務(wù)實(shí)例
let requestTask = LZRequestTask.init(urlRecord)
//將網(wǎng)絡(luò)請(qǐng)求任務(wù)加入操作隊(duì)列
sharePendingOperations.requestQueue.addOperation(requestTask)
}
4、viewController里發(fā)起網(wǎng)絡(luò)請(qǐng)求
//同時(shí)發(fā)起多個(gè)網(wǎng)絡(luò)請(qǐng)求
func testRequestTasks() {
RNetUtil.shareManager.requestPOSTWithQueue(url: url, paramter: "0") { (state, data) in
print(state,data)
}
RNetUtil.shareManager.requestPOSTWithQueue(url: url, paramter: "0") { (state, data) in
print(state,data)
}
RNetUtil.shareManager.requestPOSTWithQueue(url: url, paramter: "0") { (state, data) in
print(state,data)
}
}
5、請(qǐng)求結(jié)果
失敗時(shí)

失敗時(shí).gif
成功時(shí)

成功時(shí).gif
基本解決了文章開頭提出的問題。
有什么改進(jìn)意見或者好的想法,歡迎大家提出。