Swift Alamofire回调导致数据库多线程访问错误

Swift Alamofire callback causes database multithread access error

我正在使用 Alamofire.upload,在 encodingCompletion 回调中我想更新数据库。

我为每个数据库访问使用 DBManager.shared.database 连接,但这似乎会导致问题,因为我得到异常,多个线程尝试同时使用相同的连接。

是否有一些关于如何使用回调来防止此类问题的指南?

我将为您提供一些使用 Alamofire 发布数据的示例代码。我希望它易于理解并有所帮助。如果有什么不清楚的地方,请告诉我。

func addProduct(token:String,product:Product, completion:@escaping( Error? )->Void)
{
    let addProductHeader:HTTPHeaders   = [
                                    "token":"\(token)",

                                        "Accept":"application/json"
                                       ]

    let addProductParameter:Parameters = [
                                          "name"        :   "\(product.name!)",
                                          "manufacture" :   "\(product.manufacture!)",
                                          "description" :   "\(product.descriptionField!)",
                                          "amount"      :   product.amount!,
                                          "quantity"    :   product.quantity!,
                                          "date"        :   "\(product.date!)"
                                         ]

    AF.request("Enter Your Server DB Link Here", method: .post, parameters: addProductParameter, encoding: JSONEncoding.default, headers: addProductHeader).responseJSON
        {
            (response) in
            let encode = JSONEncoder()
            encode.outputFormatting = .prettyPrinted
            do
            {
                let jsonData = try encode.encode(product)
                print(jsonData)

                if let jsonString = String(data: jsonData, encoding: .utf8)
                {
                    print(jsonString)
                }
                completion( nil )
            }
            catch
            {
                print(error.localizedDescription)
                completion(error)
            }
        }
}

听起来您需要同步数据库访问。在数据库单例旁边创建静态 DispatchQueue 并通过该队列分派所有数据库访问的最简单方法。

编辑:类似于:

final class DBManager {
    static let shared = DBManager()
    static let queue = DispatchQueue(label: "your.identifier.here.DBManagerQueue")
}

像这样使用它:

... in a completion handler far far away ...
{ response in
    DBManager.queue.async {
        // Do something with the database
    }
}

但是,更好的解决方案是将所有这些队列置于您的 DBManager 内部,以便它的所有用户始终是线程安全的。在您可以执行此类重构之前,这只是一个权宜之计。