Swift實(shí)現(xiàn)一個(gè)任務(wù)隊(duì)列

這幾天項(xiàng)目中需要用到離線請(qǐng)求,于是我就想到了利用隊(duì)列來(lái)實(shí)現(xiàn)這個(gè)功能,首先這個(gè)隊(duì)列需要的功能如下。

  • 隊(duì)列能夠添加任務(wù)
  • 隊(duì)列能夠被持久化到本地(從本地解析到內(nèi)存)
  • 任務(wù)之間可以有依賴(lài)關(guān)系
  • 任務(wù)失敗能夠自動(dòng)重試,可以設(shè)置重試次數(shù)

明確了需求以后就可以開(kāi)干了。說(shuō)到隊(duì)列,我立馬想到了FIFO的隊(duì)列,也就是先進(jìn)先出的隊(duì)列,與棧的模型剛好反過(guò)來(lái)。iOS中并沒(méi)有現(xiàn)在的隊(duì)列數(shù)據(jù)結(jié)構(gòu)可以用,但是iOS里面有一個(gè)東西叫做NSOperationQueue這貨不是一個(gè)普通的隊(duì)列,他的功能十分的強(qiáng)大,能夠處理并發(fā)的操作,是蘋(píng)果在cocoa層對(duì)多線程的一層封裝。他有一個(gè)屬性叫做maxConcurrentOperationCount,這個(gè)指定了能夠有多少個(gè)任務(wù)能夠在同一時(shí)間被執(zhí)行,如果大于1那么就是并行的隊(duì)列,如果等于1就是串行的隊(duì)列。這個(gè)模型就像一間房子,里面有很多人,maxConcurrentOperationCount就是門(mén)的數(shù)量,門(mén)越多可以同時(shí)出去的人就越多,還有就是如果人的地位越高,也就是說(shuō)任務(wù)的優(yōu)先級(jí)越高的話是可以先出去的。

那么我們就通過(guò)改造NSOperationQueue來(lái)實(shí)現(xiàn)我們自己的隊(duì)列。

首先我們繼承NSOperationQueue來(lái)新建一個(gè)類(lèi)Queue

public class Queue: NSOperationQueue {
    ...
}

隊(duì)列有一些基本的屬性。比如說(shuō)任務(wù)的名字,最大并發(fā)數(shù)量,最大重試次數(shù)等。

/// the max times of retries when the task failing
    public let maxRetries: Int//最大重試次數(shù)
    var taskCallbacks = [String: TaskCallBack]()存放任務(wù)執(zhí)行方法的數(shù)組
    var taskList = [String: QueueTask]()隊(duì)列任務(wù)數(shù)組
    let serializationProvider: QueueSerializationProvider?//序列化助手
    let logProvider: QueueLogProvider?//log助手
    
    public required init(queueName: String, maxConcurrency: Int = 1,
        maxRetries: Int = 5,
        serializationProvider: QueueSerializationProvider? = nil,
        logProvider: QueueLogProvider? = nil) {
            
            self.maxRetries = maxRetries
            self.serializationProvider = serializationProvider
            self.logProvider = logProvider
            super.init()
            self.name = queueName
            self.maxConcurrentOperationCount = maxConcurrency
    }

然后繼承NSOperation來(lái)新建一個(gè)QueueTask

任務(wù)也有一些一些基本的屬性,比如說(shuō)所屬隊(duì)列,任務(wù)ID,任務(wù)類(lèi)型,這里通過(guò)任務(wù)類(lèi)型來(lái)對(duì)任務(wù)進(jìn)行分組,讓同一組的任務(wù)采用相同的處理方法。


public class QueueTask: NSOperation {
    public let queue: Queue
    public var taskID: String
    public var taskType: String
    public var retries: Int
    public let created: NSDate
    public var started: NSDate?
    public var userInfo: AnyObject?
}

現(xiàn)在最基本的樣子已經(jīng)有了,現(xiàn)在有了任務(wù)和隊(duì)列,那么下一步就需要把任務(wù)添加到隊(duì)列里面。
這里我們來(lái)重寫(xiě)NSOperationQueueaddOperation方法,

/**
     add Queue task to the queue and it will automaticly invoke the start method
     
     - parameter op: Queuetask
     */
    public override func addOperation(op: NSOperation) {
        if let task = op as? QueueTask {
            taskList[task.taskID] = task
            print(taskList)
        }
        super.addOperation(op)
    }

這里將任務(wù)添加到了NSOperationQueue同時(shí)也加到了taskList里面,任務(wù)完成之后會(huì)從里面移除,這里這樣做主要是講任務(wù)直接持久化到本地,只有在任務(wù)真正完成之后才會(huì)被移除,這樣即使中間退出了應(yīng)用任務(wù)也不會(huì)丟失,下次再打開(kāi)應(yīng)用的時(shí)候會(huì)自動(dòng)的從本地把讓任務(wù)加載到隊(duì)列之中。這個(gè)在處理一些離線網(wǎng)絡(luò)請(qǐng)求的場(chǎng)景的時(shí)候很有幫助。在離線情況下對(duì)本地?cái)?shù)據(jù)進(jìn)行操作,相應(yīng)的網(wǎng)絡(luò)請(qǐng)求會(huì)暫存在隊(duì)列之中。等待網(wǎng)絡(luò)恢復(fù)之后再進(jìn)行請(qǐng)求。

這里注意到addOperation方法執(zhí)行之后任務(wù)會(huì)直接進(jìn)去pending狀態(tài),相當(dāng)于自動(dòng)調(diào)用了Operation的start方法。

這里可以看到Queue中有這么一個(gè)方法,根據(jù)任務(wù)類(lèi)型來(lái)查找不同的執(zhí)行方法。

func runTask(task: QueueTask) {
        if let callback = taskCallbacks[task.taskType] {
             callback(task)
        } else {
            print("no callback registerd for task")
        }
    }

完成之后會(huì)從隊(duì)列中被移除。

func taskComplete(op: NSOperation) {
        if let task = op as? QueueTask {
            taskList.removeValueForKey(task.taskID)
        }
    }

具體的代碼見(jiàn)Github

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,614評(píng)論 19 139
  • NSThread 第一種:通過(guò)NSThread的對(duì)象方法 NSThread *thread = [[NSThrea...
    攻城獅GG閱讀 955評(píng)論 0 3
  • 一、什么是ASIHTTPRequest 使用iOS SDK中的HTTP網(wǎng)絡(luò)請(qǐng)求API,相當(dāng)?shù)膹?fù)雜,調(diào)用很繁瑣,AS...
    Bo_cake閱讀 408評(píng)論 0 1
  • 一、為什么要用 當(dāng)我們?cè)趯?xiě)程序的時(shí)候,我們通常會(huì)遇到一些很費(fèi)時(shí)的一些操作。比如離線下載、本地?cái)?shù)據(jù)的存儲(chǔ)等等,在做這...
    Go丶Pikachu閱讀 243評(píng)論 0 1
  • 原文地址 http://www.cnblogs.com/kenshincui/p/3983982.html 大家都...
    怎樣m閱讀 1,428評(píng)論 0 1

友情鏈接更多精彩內(nèi)容