Swift在后台更新UITableView

时间:2015-04-21 03:20:27

标签: ios multithreading uitableview swift asynchronous

我试图在后台更新我的UITableView。虽然我当前的代码正在运行,但我遇到了两个主要错误。

更详细。我使用coreData来填充单元格。但是我还需要连接2个API。

目前。我有两个功能:

loadSuggestions()updateSuggestions()

loadSuggestions填充获取正确的信息,显示正常。

updateSuggestions删除所有当前数据,获取新数据,将其保存到CoreData中,然后重新加载UITableView。 (这个函数作为loadSuggestions()函数中的最后一个函数,在后台运行)

所以我的主要问题。是我加载建议的时候。如果我在UITableView完成更新之前尝试与UITableView进行交互,我会收到错误:fatal error: Array index out of range原因很简单。我在我的函数开头删除了CoreData。在此期间,它期望我的数组为0,但向下滚动显然会尝试在数组索引之外加载数据。

但我不知道如何解决上述问题。

我的第二个不太重要的问题在于/ performance /? updateSuggestions()完成运行后。它实际上并没有使用更改的数据更新我的UITableView,直到几秒钟后,或者我与UITableView进行交互。它当然应该更新它完成更新的那一刻?

我不清楚如何解决这两个问题中的任何一个问题。因此,为什么我在这里。

这是我的2个函数的代码:

loadSuggestions()

func loadSuggestions() {

    println("----- Loading Data -----")
    // Set the managedContext again.
    managedContext = appDelegate.managedObjectContext!

    // Check what API to get the data from
    if Formula == 0 {
        formulaEntity = "TrialFormulaStock"
        println("Setting Entity: \(formulaEntity)")
        formulaAPI = NSURL(string: "http://api.com/json/entry_weekly.json")
    } else if Formula == 1 {
        formulaEntity = "ProFormulaStock"
        println("Setting Entity: \(formulaEntity)")
        formulaAPI = NSURL(string: "http://api.com/json/entry_weekly.json")
    } else if Formula == 2 {
        formulaEntity = "PremiumFormulaStock"
        formulaAPI = NSURL(string: "http://api.com/json/proff_weekly.json")
        println("Setting Entity: \(formulaEntity)")
    } else if Formula == 3 {
        formulaEntity = "PlatinumFormulaStock"
        println("Setting Entity: \(formulaEntity)")
        formulaAPI = NSURL(string: "http://api.com/json/fund_weekly.json")
    }

    // Delete all the current objects in the dataset
    let fetchRequest = NSFetchRequest(entityName: formulaEntity)
    let a = managedContext.executeFetchRequest(fetchRequest, error: nil) as! [NSManagedObject]
    stocks.removeAll(keepCapacity: false)
    for mo in a {
        stocks.append(mo)
    }
    // Removing them from the array

    // Saving the now empty context.
    managedContext.save(nil)

    // Reload the tableview with the new data.
    self.tableView.reloadData()
    self.view.hideLoading()
    self.refreshControl.endRefreshing()

    dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_USER_INITIATED.value), 0)) {
        self.updateSuggestions()
    }

}

和updateSuggestions:

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")
    }
}

我在后台运行updateSuggestions()的原因是因为它需要很长时间才能进行所有API调用。并且用户需要能够在加载时进行交互并查看当前数据。

/可能/不相关,我也收到了一些内存警告。

非常感谢任何帮助!

0 个答案:

没有答案