Aggiornamento rapido di UITableView con nuovi dati

Sto cercando di ripopolare il mio UITableView con i dati di un'altra chiamata JSON.

Comunque la mia attuale configuration non sembra funzionare, e mentre ci sono molte domande identiche su SO, le risposte che ho potuto trovare sono già state provate.

Sto salvando i miei dati API in oggetti entity framework; CoreData . E sto riempiendo il mio UITableView con le mie entity framework; CoreData .

Nella mia attuale configuration ho 3 diverse chiamate API che hanno una diversa quantità di dati e, naturalmente, valori diversi. Devo essere in grado di passare tra questi 3 set di dati, ed è quello che sto cercando di realizzare ora. (finora senza progressi).

Ho una function chiamata "loadSuggestions", che è where presumo la mia colpa.

  • Per prima cosa controllo una connessione internet.

  • Ho impostato il managedObjectContext

  • Controllo quali API devo call (questo è determinato prima che la function venga chiamata e ho controllato che funzioni come previsto)

  • Elimina tutti i dati correnti dall'entity framework; che sta tentando di call. (Ho anche provato a eliminare i dati dagli ultimi dati caricati da UITableView . Ciò non ha cambiato nulla). Ho anche controllato che funzioni. Dopo aver cancellato i dati, ho controllato che printingsse un arrays vuoto, ho anche provato a registrare gli oggetti che elimina per essere sicuro.

  • Prendo quindi i nuovi dati, salvandoli in variables temporanee. Quindi salvalo nei miei dati principali.

  • Quindi faccio la mia seconda chiamata API (dipende da una variabile dal primo), recupero i dati e li salviamo allo stesso modo.

  • Appendo l'object all'arrays che UITableView riempie dalle sue celle. (Ho controllato che sia printingto correttamente)

  • E infine ricarico il TableView. (non cambia nulla)

Ecco la function:

 func loadSuggestions() { println("----- Loading Data -----") // Check for an internet connection. if Reachability.isConnectedToNetwork() == false { println("ERROR: -> No Internet Connection <-") } else { // 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] for mo in a { managedContext.deleteObject(mo) } // Removing them from the arrays 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 // The second API call doesn't always find something, so checking if it exists is importnt. 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 arrays. Which fills the UITableView stocks.append(stock) } // Reload the tableview with the new data. self.tableView.reloadData() } } 

Attualmente, quando spingo su questa viewController, questa function viene chiamata in viewDidAppear in viewDidAppear modo:

 override func viewDidAppear(animated: Bool) { super.viewDidAppear(true) tableView.allowsSelection = true if isFirstTime { loadSuggestions() isFirstTime = false } } 

Compila popolarmente il TableView e tutto sembra funzionare come pianificato.

Tuttavia se apro il mio menu slide-out e chiamo una function per caricare dati diversi, non succede nulla, ecco una function di esempio:

 func platinumFormulaTapGesture() { // Menu related actions selectView(platinumFormulaView) selectedMenuItem = 2 // Setting the data to load Formula = 3 // Sets the viewController. (this will mostly be the same ViewController) menuTabBarController.selectedIndex = 0 // Set the new title navigationController?.navigationBar.topItem!.title = "PLATINUM FORMULA" // And here I call the loadSuggestions function again. (this does run) SuggestionsViewController().loadSuggestions() } 

Ecco le 2 rilevanti funzioni di tableView:

numero di righe:

 func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return stocks.count } 

E cellForRowAtIndexPath, (questo è where ho impostato le mie celle con il CoreData)

 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("com.mySuggestionsCell", forIndexPath: indexPath) as! mySuggestionsCell let formulaStock = stocks[indexPath.row] cell.stockNameLabel.text = formulaStock.valueForKey("name") as! String! cell.tickerLabel.text = formulaStock.valueForKey("ticker") as! String! action = formulaStock.valueForKey("action") as! String! suggestedPrice = formulaStock.valueForKey("suggestedPrice") as! Float let suggestedPriceString = "Suggested Price\n$\(suggestedPrice.roundTo(2))" as NSString var suggestedAttributedString = NSMutableAttributedString(string: suggestedPriceString as String) suggestedAttributedString.addAttributes(GrayLatoRegularAttribute, range: suggestedPriceString.rangeOfString("Suggested Price\n")) suggestedAttributedString.addAttributes(BlueHalisRBoldAttribute, range: suggestedPriceString.rangeOfString("$\(suggestedPrice.roundTo(2))")) cell.suggestedPriceLabel.attributedText = suggestedAttributedString if action == "SELL" { cell.suggestionContainer.backgroundColor = UIColor.formulaGreenColor() } if let lastPrice = formulaStock.valueForKey("lastPrice") as? Float { var lastPriceString = "Last Price\n$\(lastPrice.roundTo(2))" as NSString var lastAttributedString = NSMutableAttributedString(string: lastPriceString as String) lastAttributedString.addAttributes(GrayLatoRegularAttribute, range: lastPriceString.rangeOfString("Last Price\n")) percentDifference = ((lastPrice/suggestedPrice)*100.00)-100 if percentDifference > 0 && action == "BUY" { lastAttributedString.addAttributes(RedHalisRBoldAttribute, range: lastPriceString.rangeOfString("$\(lastPrice.roundTo(2))")) } else if percentDifference <= 0 && percentDifference > -100 && action == "BUY" { lastAttributedString.addAttributes(GreenHalisRBoldAttribute, range: lastPriceString.rangeOfString("$\(lastPrice.roundTo(2))")) } else if percentDifference <= 0 && percentDifference > -100 && action == "SELL" { lastAttributedString.addAttributes(RedHalisRBoldAttribute, range: lastPriceString.rangeOfString("$\(lastPrice.roundTo(2))")) } else if percentDifference == -100 { lastPriceString = "Last Price\nN/A" as NSString lastAttributedString = NSMutableAttributedString(string: lastPriceString as String) lastAttributedString.addAttributes(GrayLatoRegularAttribute, range: lastPriceString.rangeOfString("Last Price\n")) lastAttributedString.addAttributes(BlackHalisRBoldAttribute, range: lastPriceString.rangeOfString("N/A")) } cell.lastPriceLabel.attributedText = lastAttributedString } else { println("lastPrice nil") } weight = formulaStock.valueForKey("weight") as! Float cell.circleChart.percentFill = weight let circleChartString = "\(weight.roundTo(2))%\nWEIGHT" as NSString var circleChartAttributedString = NSMutableAttributedString(string: circleChartString as String) circleChartAttributedString.addAttributes(BlueMediumHalisRBoldAttribute, range: circleChartString.rangeOfString("\(weight.roundTo(2))%\n")) circleChartAttributedString.addAttributes(BlackSmallHalisRBoldAttribute, range: circleChartString.rangeOfString("WEIGHT")) cell.circleChartLabel.attributedText = circleChartAttributedString cell.selectionStyle = UITableViewCellSelectionStyle.None return cell } 

Definisco la mia appDelegate come la prima cosa nella mia class:

 let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate var managedContext = NSManagedObjectContext() 

Penso che sia tutto il codice che potrebbe essere la causa del bug. Ancora una volta penso che la causa più probabile sarebbe nella function loadSuggestions .

Per forzare l'aggiornamento di tableView ho anche provato a call setNeedsDisplay e setNeedsLayout su self.view e tableView , nessuno dei quali sembrava fare nulla.

Qualche consiglio nel capire perché questo TableView si rifiuta di aggiornare sarebbe di enorme aiuto!

E mi scuso per i muri del codice, ma non sono stato in grado di trovare l'origine esatta del problema.

Solutions Collecting From Web of "Aggiornamento rapido di UITableView con nuovi dati"

Questa row nella function platinumFormulaTapGesture non è corretta,

 SuggestionsViewController().loadSuggestions() 

Questo crea una nuova istanza di SuggestionsViewController, che non è quella che hai sullo schermo. Devi get un puntatore a quello che hai. Il modo in cui lo fai dipende dalla gerarchia del tuo controller, che non hai spiegato abbastanza pienamente.