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