使用 SQLite 数据库的 DispatchGroup
DispatchGroup with SQLite database
我正在努力了解 GCD,特别是 DispatchGroup 以通过 FMDB 包装器组织到 SQLite 数据库的下载。我的应用执行以下操作:
- 在应用程序启动时使用 SQL 数据库从远程服务器下载可用主题的信息。将这些本地保存在 SQLite db 中以供将来使用,并通过 UITableViewController
显示可用内容
- 如果选择了一个主题,其内容将从服务器下载并保存在本地以供将来使用。我这样做而不是在启动时一次完成,因为这是应用程序内购买的前身。我还在这里下载了一些其他的东西。然后转到主题内容的新表格视图。
- 我可以通过将下载和保存功能与完成处理程序链接在一起来实现上述目标,但是我想使用 DispatchGroup,以便将来可以使用
wait(timeout:)
功能。
但是,在我实施 DispatchGroup(如下)时,我收到了以下错误。
API call with NULL database connection pointer
[logging] misuse at line 125820 of [378230ae7f]
还有
BUG IN CLIENT OF libsqlite3.dylib: illegal multi-threaded access to database connection
代码如下:
didSelectRow
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//Download from server
if availableSubjects[indexPath.row].isDownloaded == 0 {
//CHAINING THIS WAY WORKS
/* downloadModel.downloadCaseBundle(withSubjectID: indexPath.row, completion: {
self.downloadModel.downloadToken(forSubject: indexPath.row, completion: {
self.caseBundle = DBManager.sharedDBManager.getCaseBundle(forSubject: indexPath.row)
self.availableSubjects[indexPath.row].isDownloaded = 1
DispatchQueue.main.async {
self.performSegue(withIdentifier: "showCaseList", sender: self)
}
})
})*/
let dispatchGroup = DispatchGroup()
//Download content
dispatchGroup.enter()
downloadModel.downloadCaseBundle(withSubjectID: indexPath.row) {
dispatchGroup.leave()
}
//Download token
dispatchGroup.enter()
downloadModel.downloadToken(forSubject: indexPath.row) {
dispatchGroup.leave()
}
//Execute
dispatchGroup.notify(queue: .main) {
self.caseBundle = DBManager.sharedDBManager.getCaseBundle(forSubject: indexPath.row)
self.availableSubjects[indexPath.row].isDownloaded = 1
self.performSegue(withIdentifier: "showCaseList", sender: self)
}
} else { //Already downloaded, just retrieve from local db and present
caseBundle = DBManager.sharedDBManager.getCaseBundle(forSubject: indexPath.row)
self.performSegue(withIdentifier: "showCaseList", sender: self)
}
}
下载模型、下载案例包
downloadToken 函数大致相同
func downloadCaseBundle(withSubjectID subjectID: Int, completion: @escaping () -> Void) {
let urlPath = "someStringtoRemoteDB"
let url: URL = URL(string: urlPath)!
let defaultSession = Foundation.URLSession(configuration: URLSessionConfiguration.default)
let task = defaultSession.dataTask(with: url) { (data, response, error) in
if error != nil {
print("Error")
} else {
print("cases downloaded")
self.parseCasesJSON(data!, header: self.remoteMasterTable, forSubject: subjectID)
completion()
}
}
task.resume()
}
下载模式,解析JSON
func parseCasesJSON(_ data:Data, header: String, forSubject subjectID: Int) {
var jsonResult = NSArray()
var jsonElement = NSDictionary()
let cases = NSMutableArray()
do {
jsonResult = try JSONSerialization.jsonObject(with: data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
} catch let error as NSError {
print(error)
print("error at serialisation")
}
//Iterate through JSON result (i.e. case), construct and append to cases array
for i in 0 ..< jsonResult.count {
jsonElement = jsonResult[i] as! NSDictionary
var caseObject = CaseModel()
//The following insures none of the JsonElement values are nil through optional binding
if let uniqueID = jsonElement["id"] as? Int,
let subjectTitle = jsonElement["subjectTitle"] as? String,
let subjectID = jsonElement["subjectID"] as? Int,
let questionID = jsonElement["questionID"] as? Int,
//And so on
{
caseObject.uniqueID = uniqueID
caseObject.subjectTitle = subjectTitle
caseObject.subjectID = subjectID
caseObject.questionID = questionID
//And so on
}
cases.add(caseObject)
}
DBManager.sharedDBManager.saveCasesLocally(dataToSave: cases as! [CaseModel])
DBManager.sharedDBManager.setSubjectAsDownloaded(forSubjectID: subjectID)
}
原来这与那些方法无关,我需要在我的 DBManager
单例中实现 FMDatabaseQueue
而不是 FMDatabase
。
我正在努力了解 GCD,特别是 DispatchGroup 以通过 FMDB 包装器组织到 SQLite 数据库的下载。我的应用执行以下操作:
- 在应用程序启动时使用 SQL 数据库从远程服务器下载可用主题的信息。将这些本地保存在 SQLite db 中以供将来使用,并通过 UITableViewController 显示可用内容
- 如果选择了一个主题,其内容将从服务器下载并保存在本地以供将来使用。我这样做而不是在启动时一次完成,因为这是应用程序内购买的前身。我还在这里下载了一些其他的东西。然后转到主题内容的新表格视图。
- 我可以通过将下载和保存功能与完成处理程序链接在一起来实现上述目标,但是我想使用 DispatchGroup,以便将来可以使用
wait(timeout:)
功能。
但是,在我实施 DispatchGroup(如下)时,我收到了以下错误。
API call with NULL database connection pointer
[logging] misuse at line 125820 of [378230ae7f]
还有
BUG IN CLIENT OF libsqlite3.dylib: illegal multi-threaded access to database connection
代码如下:
didSelectRow
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//Download from server
if availableSubjects[indexPath.row].isDownloaded == 0 {
//CHAINING THIS WAY WORKS
/* downloadModel.downloadCaseBundle(withSubjectID: indexPath.row, completion: {
self.downloadModel.downloadToken(forSubject: indexPath.row, completion: {
self.caseBundle = DBManager.sharedDBManager.getCaseBundle(forSubject: indexPath.row)
self.availableSubjects[indexPath.row].isDownloaded = 1
DispatchQueue.main.async {
self.performSegue(withIdentifier: "showCaseList", sender: self)
}
})
})*/
let dispatchGroup = DispatchGroup()
//Download content
dispatchGroup.enter()
downloadModel.downloadCaseBundle(withSubjectID: indexPath.row) {
dispatchGroup.leave()
}
//Download token
dispatchGroup.enter()
downloadModel.downloadToken(forSubject: indexPath.row) {
dispatchGroup.leave()
}
//Execute
dispatchGroup.notify(queue: .main) {
self.caseBundle = DBManager.sharedDBManager.getCaseBundle(forSubject: indexPath.row)
self.availableSubjects[indexPath.row].isDownloaded = 1
self.performSegue(withIdentifier: "showCaseList", sender: self)
}
} else { //Already downloaded, just retrieve from local db and present
caseBundle = DBManager.sharedDBManager.getCaseBundle(forSubject: indexPath.row)
self.performSegue(withIdentifier: "showCaseList", sender: self)
}
}
下载模型、下载案例包
downloadToken 函数大致相同
func downloadCaseBundle(withSubjectID subjectID: Int, completion: @escaping () -> Void) {
let urlPath = "someStringtoRemoteDB"
let url: URL = URL(string: urlPath)!
let defaultSession = Foundation.URLSession(configuration: URLSessionConfiguration.default)
let task = defaultSession.dataTask(with: url) { (data, response, error) in
if error != nil {
print("Error")
} else {
print("cases downloaded")
self.parseCasesJSON(data!, header: self.remoteMasterTable, forSubject: subjectID)
completion()
}
}
task.resume()
}
下载模式,解析JSON
func parseCasesJSON(_ data:Data, header: String, forSubject subjectID: Int) {
var jsonResult = NSArray()
var jsonElement = NSDictionary()
let cases = NSMutableArray()
do {
jsonResult = try JSONSerialization.jsonObject(with: data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
} catch let error as NSError {
print(error)
print("error at serialisation")
}
//Iterate through JSON result (i.e. case), construct and append to cases array
for i in 0 ..< jsonResult.count {
jsonElement = jsonResult[i] as! NSDictionary
var caseObject = CaseModel()
//The following insures none of the JsonElement values are nil through optional binding
if let uniqueID = jsonElement["id"] as? Int,
let subjectTitle = jsonElement["subjectTitle"] as? String,
let subjectID = jsonElement["subjectID"] as? Int,
let questionID = jsonElement["questionID"] as? Int,
//And so on
{
caseObject.uniqueID = uniqueID
caseObject.subjectTitle = subjectTitle
caseObject.subjectID = subjectID
caseObject.questionID = questionID
//And so on
}
cases.add(caseObject)
}
DBManager.sharedDBManager.saveCasesLocally(dataToSave: cases as! [CaseModel])
DBManager.sharedDBManager.setSubjectAsDownloaded(forSubjectID: subjectID)
}
原来这与那些方法无关,我需要在我的 DBManager
单例中实现 FMDatabaseQueue
而不是 FMDatabase
。