swift - 结合 Realm 执行异步串行请求的问题

标签 swift multithreading asynchronous realm

我想结合 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 请求,OperationQueueDispatchSemaphore 结合使用。

    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/

相关文章:

ios - 在纵横比中设置图像高度在 Xcode 中填充自动布局

ios - 使用 Simple TableView Swift 进行单元格构造的奇怪行为

Swift 4 - 如何在不重复代码的情况下调用从多个函数中的函数返回的一段代码?

javascript - 异步函数返回未定义且 $q 延迟

linux - 如何在 perl 中使用 O_ASYNC 和 fcntl?

ios - 在单元格中切换,不在 tableView 方法中传递正确的 bool 值

java - 执行器正在执行两次

java - 仅让类的一部分等待执行,无论是否有线程?

java - 这是合适的定制同步器吗?

javascript - 使用node.js异步系列插入错误