Marwen Jamel Marwen Jamel - 7 months ago 31
Swift Question

Array doesn't save

Getting a JSON object from a rest web service I get the data from the object and I want to show it in a tableview.

class TableViewController1: UITableViewController {
var nomProduit = ["ok"]
var prixProduit = [""]
var vt1 : String?
var vt2 : String?

var i : Int!
var compteur1:Int!
var resultat1:NSArray?
var x : AnyObject?


override func viewDidLoad() {


super.viewDidLoad()
// \(detectionString)
let str:String = "http://vps43623.ovh.net/yamoinscher/api/products/6194005492077"
let url = NSURL(string: str)!

let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) -> Void in

if let urlContent = data {

do {

let jsonResult = try NSJSONSerialization.JSONObjectWithData(urlContent, options: NSJSONReadingOptions.MutableContainers)


self.resultat1 = jsonResult["meme_categorie"] as? NSArray

self.compteur1 = self.resultat1!.count
print(self.compteur1!)
//self.value = (compteur1 as? Int)!

for self.i=0 ; self.i < self.compteur1! ; self.i = self.i+1 {
if let aStatus = self.resultat1![self.i] as? NSDictionary{
self.vt1 = aStatus["libelle_prod"]! as? String
self.nomProduit.append(self.vt1!)
self.vt2 = aStatus["prix"]! as? String
self.prixProduit.append(self.vt2!)
//print(self.nomProduit[self.i])


}

}


} catch {

print("JSON serialization failed")

}


}


}

task.resume()


}


Then My problem is that this array stays nil:

self.prixProduit.append(self.vt2!)


here is the rest of my code

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

return 17
}


override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

let cell = tableView.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as! customCell1

// cell.PrixSim.text = nomProduit[indexPath.row]


print(self.nomProduit[0])



return cell
}

Answer

First of all use a custom struct for the category objects, it makes things so much easier.

At the beginning of TableViewController1

class TableViewController1: UITableViewController {

declare this struct

  struct Produit {
    var id : String
    var prix : String
    var title : String
  }

and a data source array (forget all your other properties / variables)

var produits = [Produit]()

In viewDidLoad get the data, populate the data source array and reload the table view on the main thread.
This code uses Swift native collection types

  override func viewDidLoad() {

    super.viewDidLoad()
    // \(detectionString)
    let str = "http://vps43623.ovh.net/yamoinscher/api/products/6194005492077"
    let url = NSURL(string: str)!

    let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) -> Void in

      if let urlContent = data {

        do {
          let jsonObject = try NSJSONSerialization.JSONObjectWithData(urlContent, options: [])
          if let jsonResult = jsonObject as? [String:AnyObject] {
            if let memeCategorie = jsonResult["meme_categorie"] as? [[String:String]] {
              for categorie in memeCategorie {
                if let prix = categorie["prix"], title = categorie["libelle_prod"], id = categorie["id"] {
                   self.produits.append(Produit(id: id, prix: prix, title: title))
                 }
              }
              dispatch_async(dispatch_get_main_queue()) {
                 self.tableView.reloadData()
              }
            }
          }
        } catch {
          print("JSON serialization failed", error)
        }
      } else if let connectionError = error {
          print("connection error", connectionError)
      }
    }      
    task.resume()
  }

In numberOfRowsInSection return the actual number of items rather than a hard-coded number.
You can omit numberOfSectionsInTableView since the default value is 1.

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

In cellForRowAtIndexPath get the item by index path and assign the values to your labels (or whatever). For now the values are just printed out.

 override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as! customCell1

    let produit = produits[indexPath.row]

    print(produit.id, produit.title, produit.prix)
    return cell
  }

}