Ios 在后台快速更新UITableView
我正在尝试在后台更新我的UITableView。当我当前的代码运行时,我有两个主要错误 更详细地说。我用coreData来填充单元格。但我还有两个API需要连接 现在。我有两个功能:Ios 在后台快速更新UITableView,ios,multithreading,uitableview,swift,asynchronous,Ios,Multithreading,Uitableview,Swift,Asynchronous,我正在尝试在后台更新我的UITableView。当我当前的代码运行时,我有两个主要错误 更详细地说。我用coreData来填充单元格。但我还有两个API需要连接 现在。我有两个功能: loadSuggestions()和updateSuggestions() loadSuggestionsfills获取正确的信息并显示良好 updatesSuggestions删除所有当前数据,获取新数据,将其保存到CoreData中,然后重新加载UITableView。(此函数作为我的loadSuggestio
loadSuggestions()
和updateSuggestions()
loadSuggestions
fills获取正确的信息并显示良好
updatesSuggestions
删除所有当前数据,获取新数据,将其保存到CoreData中,然后重新加载UITableView
。(此函数作为我的loadSuggestions()
函数中的最后一项在后台运行)
所以我的主要问题是。就是当我加载建议时。如果在更新完成之前尝试与UITableView交互,我会得到错误:致命错误:数组索引超出范围
原因很简单。我在函数的开头删除CoreData。在此期间,它希望我的数组为0,但向下滚动显然会尝试在数组索引之外加载数据
但是,我不知道如何解决上述问题
我的第二个次要问题是/performance/?updateSuggestions()完成后运行。直到几秒钟之后,或者如果我与UITableView
交互,它才实际使用更改的数据更新我的UITableView
。当然,它应该在完成更新后立即更新
我不知道如何解决这两个问题中的任何一个。这就是我来这里的原因
以下是我的两个函数代码:
加载建议()
和更新建议:
func updateSuggestions() {
println("Updating Suggestions")
if Reachability.isConnectedToNetwork() == false {
println("ERROR: -> No Internet Connection <-")
} else {
// Delete all the current objects in the dataset
let fetchRequest = NSFetchRequest(entityName: formulaEntity)
let a = managedContext.executeFetchRequest(fetchRequest, error: nil) as! [NSManagedObject]
for mo in a {
managedContext.deleteObject(mo)
}
// Removing them from the array
stocks.removeAll(keepCapacity: false)
// Saving the now empty context.
managedContext.save(nil)
// Set up a fetch request for the API data
let entity = NSEntityDescription.entityForName(formulaEntity, inManagedObjectContext:managedContext)
var request = NSURLRequest(URL: formulaAPI!)
var data = NSURLConnection.sendSynchronousRequest(request, returningResponse: nil, error: nil)
var formula = JSON(data: data!)
// Loop through the api data.
for (index: String, actionable: JSON) in formula["actionable"] {
// Save the data into temporary variables
stockName = actionable["name"].stringValue
ticker = actionable["ticker"].stringValue
action = actionable["action"].stringValue
suggestedPrice = actionable["suggested_price"].floatValue
weight = actionable["percentage_weight"].floatValue
// Set up CoreData for inserting a new object.
let stock = NSManagedObject(entity: entity!,insertIntoManagedObjectContext:managedContext)
// Save the temporary variables into coreData
stock.setValue(stockName, forKey: "name")
stock.setValue(ticker, forKey: "ticker")
stock.setValue(action, forKey: "action")
stock.setValue(suggestedPrice, forKey: "suggestedPrice")
stock.setValue(weight, forKey: "weight")
// Get ready for second API call.
var quoteAPI = NSURL(string: "http://dev.markitondemand.com/Api/v2/Quote/json?symbol=\(ticker)")
// Second API fetch.
var quoteRequest = NSURLRequest(URL: quoteAPI!)
var quoteData = NSURLConnection.sendSynchronousRequest(quoteRequest, returningResponse: nil, error: nil)
if quoteData != nil {
// Save the data from second API call to temporary variables
var quote = JSON(data: quoteData!)
betterStockName = quote["Name"].stringValue
lastPrice = quote["LastPrice"].floatValue
println("Updated lastPrice for \(betterStockName)")
// The second API call doesn't always find something, so checking if it exists is important.
if betterStockName != "" {
stock.setValue(betterStockName, forKey: "name")
}
// This can simply be set, because it will be 0 if not found.
stock.setValue(lastPrice, forKey: "lastPrice")
} else {
println("ERROR ----------------- NO DATA for \(ticker) --------------")
}
// Error handling
var error: NSError?
if !managedContext.save(&error) {
println("Could not save \(error), \(error?.userInfo)")
}
// Append the object to the array. Which fills the UITableView
stocks.append(stock)
}
self.tableView.reloadData()
println("Finished Updating Suggestions")
}
}
func更新建议(){
println(“更新建议”)
如果可达性.isconnectedtonework()=false{
普林顿("错误:->没有Internet连接我认为第二个问题是从后台线程调用reloadData造成的。对于第一个问题,您没有使用NSFetchedResultsController吗?保留数据,直到完成数据更新。然后用新数据替换旧数据。@rdelmar您是对的。将其移动到主线程修复了loading时间!再次感谢你。@Volker我理解这背后的逻辑。我不知道的是怎么做。因为我在循环每个API调用。我在保存数据。如何获取所有数据,保存它。然后只删除旧数据?
func updateSuggestions() {
println("Updating Suggestions")
if Reachability.isConnectedToNetwork() == false {
println("ERROR: -> No Internet Connection <-")
} else {
// Delete all the current objects in the dataset
let fetchRequest = NSFetchRequest(entityName: formulaEntity)
let a = managedContext.executeFetchRequest(fetchRequest, error: nil) as! [NSManagedObject]
for mo in a {
managedContext.deleteObject(mo)
}
// Removing them from the array
stocks.removeAll(keepCapacity: false)
// Saving the now empty context.
managedContext.save(nil)
// Set up a fetch request for the API data
let entity = NSEntityDescription.entityForName(formulaEntity, inManagedObjectContext:managedContext)
var request = NSURLRequest(URL: formulaAPI!)
var data = NSURLConnection.sendSynchronousRequest(request, returningResponse: nil, error: nil)
var formula = JSON(data: data!)
// Loop through the api data.
for (index: String, actionable: JSON) in formula["actionable"] {
// Save the data into temporary variables
stockName = actionable["name"].stringValue
ticker = actionable["ticker"].stringValue
action = actionable["action"].stringValue
suggestedPrice = actionable["suggested_price"].floatValue
weight = actionable["percentage_weight"].floatValue
// Set up CoreData for inserting a new object.
let stock = NSManagedObject(entity: entity!,insertIntoManagedObjectContext:managedContext)
// Save the temporary variables into coreData
stock.setValue(stockName, forKey: "name")
stock.setValue(ticker, forKey: "ticker")
stock.setValue(action, forKey: "action")
stock.setValue(suggestedPrice, forKey: "suggestedPrice")
stock.setValue(weight, forKey: "weight")
// Get ready for second API call.
var quoteAPI = NSURL(string: "http://dev.markitondemand.com/Api/v2/Quote/json?symbol=\(ticker)")
// Second API fetch.
var quoteRequest = NSURLRequest(URL: quoteAPI!)
var quoteData = NSURLConnection.sendSynchronousRequest(quoteRequest, returningResponse: nil, error: nil)
if quoteData != nil {
// Save the data from second API call to temporary variables
var quote = JSON(data: quoteData!)
betterStockName = quote["Name"].stringValue
lastPrice = quote["LastPrice"].floatValue
println("Updated lastPrice for \(betterStockName)")
// The second API call doesn't always find something, so checking if it exists is important.
if betterStockName != "" {
stock.setValue(betterStockName, forKey: "name")
}
// This can simply be set, because it will be 0 if not found.
stock.setValue(lastPrice, forKey: "lastPrice")
} else {
println("ERROR ----------------- NO DATA for \(ticker) --------------")
}
// Error handling
var error: NSError?
if !managedContext.save(&error) {
println("Could not save \(error), \(error?.userInfo)")
}
// Append the object to the array. Which fills the UITableView
stocks.append(stock)
}
self.tableView.reloadData()
println("Finished Updating Suggestions")
}
}