我想结合 Realm 执行一组串行异步请求。
我要处理的请求集用于更新远程服务器,并由包含对象类型和本地 uuid 的结构数组确定。相关对象从 Realm 数据库中获取,随后使用 Alamofire 写入服务器。
但是,获取 Realm 对象会导致错误(Realm 从不正确的线程访问
)。
func performAsyncRequest<T: Object>(objectType: T.Type, uuid: String, failure fail: (()->Void)? = nil, success succeed: @escaping () -> Void)->Void {
let realm = try! Realm()
let dataObject = realm.objects(objectType).filter("uuid == %@", uuid).first!
let parameters = self.toJson(item: dataObject)
// ** The Realm error occurs when the Alamofire request is performed **
let urlRequest = self.getRequest(objectType: T.self, with: parameters)
self.alamoFireManager.request(urlRequest) // Perform POST request
.responseString { response in
if let status = response.response?.statusCode {
if status >= 200 && status <= 299 {
succeed() // Is not reached in combination with DispatchSemaphore
} else if status >= 400 && status <= 499 {
fail?() // Is not reached in combination with DispatchSemaphore
}
}
}
}
编辑:下面的代码是在下面的答案之后编辑的(其中解决了先前的串行 Alamofire 请求问题)。
为了连续执行 Alamofire 请求,OperationQueue
与 DispatchSemaphore
结合使用。
let operationQueue = OperationQueue()
var operation: Operation!
for requestData in requests { // requestData is a struct with the object Type and a uuid
switch requestData.objectType {
case is Object1.Type:
operation = BlockOperation(block: {
let semaphore = DispatchSemaphore(value: 0)
self.performAsyncRequest(objectType: Object1.self, uuid: requestData.uuid, failure: { error in
semaphore.signal()
}) {
semaphore.signal()
}
semaphore.wait()
})
case is Object2.Type:
// ... same as for Object1 but now for Object2
// .. and so on for other Objects
}
operationQueue.addOperation(operation)
}
如以下答案所示,错误发生是因为 Realm 是线程受限的。但是,我不清楚为什么 Realm 实例会跨不同的线程传递。
通过异常断点,我确定错误发生在线程 Queue: NSOperationQueue 0x… (QOS: UTILITY) (serial)
上。这是一个不同于执行 BlockOperation
的线程(因此也是获取 Realm 对象的线程)。为什么 BlockOperation
中的方法没有在与 NSOperationQueue
相同的线程上执行?
如果有任何解决这些问题的想法,我将不胜感激。
最佳答案
Realm 和Realm 对象是线程限制的。您应该在每个线程上检索新的 Realm 实例。不要跨其他线程传递 Realm 实例。
似乎主线程因等待信号量而停止。然后在主线程上执行 Alamofire 回调。所以 semaphore.signal()
永远不会被调用,因为主线程停止了。 Alamofire 的 response*
方法可以指定 queue
回调被调用。
关于swift - 结合 Realm 执行异步串行请求的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39898969/