Note
:雖然在SO中還存在其他類似的問題,但其中沒有一個作者似乎自己控制Operation
的生命週期。請在提及另一個問題之前仔細閱讀。Alamofire請求不在NS內運行完成塊
我在Swift 3.0中創建了一個[NS]操作來下載,解析和緩存核心數據中的一些數據。
起初,我在手術中使用了main()
方法來執行手頭的任務,它運行良好。現在我需要運行幾個單獨的任務來檢索有關此步驟中獲得的每個/每個設備的信息。爲此,我需要確保設備實際上位於Core Data中,然後才能獲取其他信息。出於這個原因,我想確保在發出相關請求之前,我確定何時完成任務 - 哪一個是所有設備在緩存中安全無恙 - 何時完成。
問題是,即使我已檢查Alamofire確實執行了請求並且服務器確實發送了數據,但標記爲註釋[THIS WONT EXECUTE!
]的完成塊永遠不會執行。這導致隊列停頓,因爲操作在所述完成塊內被標記爲finished
,這是期望的行爲。
有沒有人有關於這裏可能發生什麼的任何想法?
class FetchDevices: Operation {
var container: NSPersistentContainer!
var alamofireManager: Alamofire.SessionManager!
var host: String!
var port: Int!
private var _executing = false
private var _finished = false
override internal(set) var isExecuting: Bool {
get {
return _executing
}
set {
willChangeValue(forKey: "isExecuting")
_executing = newValue
didChangeValue(forKey: "isExecuting")
}
}
override internal(set) var isFinished: Bool {
get {
return _finished
}
set {
willChangeValue(forKey: "isFinished")
_finished = newValue
didChangeValue(forKey: "isFinished")
}
}
override var isAsynchronous: Bool {
return true
}
init(usingContainer container: NSPersistentContainer, usingHost host: String, usingPort port: Int) {
super.init()
self.container = container
self.host = host
self.port = port
let configuration = URLSessionConfiguration.default
configuration.timeoutIntervalForResource = 10 // in seconds
self.alamofireManager = Alamofire.SessionManager(configuration: configuration)
}
override func start() {
if self.isCancelled {
self.isFinished = true
return
}
self.isExecuting = true
alamofireManager!.request("http://apiurlfor.devices")
.validate()
.responseJSON { response in
// THIS WONT EXECUTE!
if self.isCancelled {
self.isExecuting = false
self.isFinished = true
return
}
switch response.result {
case .success(let value):
let jsonData = JSON(value)
self.container.performBackgroundTask { context in
for (_, rawDevice):(String, JSON) in jsonData {
let _ = Device(fromJSON: rawDevice, usingContext: context)
}
do {
try context.save()
} catch {
let saveError = error as NSError
print("\(saveError), \(saveError.userInfo)")
}
self.isExecuting = false
self.isFinished = true
}
case .failure(let error):
print("May Day! May Day! \(error)")
self.isExecuting = false
self.isFinished = true
}
}
}
}
一塊可能有用的信息是,在我排隊所有的操作的方法中,我使用的所有queue.waitUntilAllOperationsAreFinished()
完成後執行完成處理程序。
感謝您花時間回答@Rob。我做了你的建議,沒有改變。我會看看'阻塞主線程'的事情,但我不明白可能導致什麼。你看到的代碼是整個Operation.There沒有更多的。 – reydelleon
好@Rob,我認爲你指出了正確的方向,但還有更多的工作要做。我在負責排隊任務的方法中使用'queue.waitUntilAllOperationsAreFinished()'。如果我評論說,隊列不會停頓,但實際上我需要等待所有操作完成,然後再調用完成處理程序。有沒有辦法解決這個問題? – reydelleon
你的回答最終給我帶來了正確的方向。我只是編輯它來添加一個鏈接到一個問題,解決了原始問題,我只有在分析問題後才發現,考慮到你的指針。 – reydelleon