2

In my mainTableView Controller, I can print the API result in the console but I have no idea how I can set these to be visible in the cells of my tableview

import UIKit
//from: https://github.com/Ramotion/folding-cell
class MainTableViewController: UITableViewController {

let kCloseCellHeight: CGFloat = 179
let kOpenCellHeight: CGFloat = 488

let kRowsCount = 100

var cellHeights = [CGFloat]()
var restApi = RestApiManager()
var items: NSDictionary = [:]


override func viewDidLoad() {
    super.viewDidLoad()

    restApi.makeCall() { responseObject, error in
        // use responseObject and error here
        //  self.json = JSON(responseObject!)

        print("print the json data from api ")
        self.items = NSDictionary(dictionary: responseObject!)
        self.tableView.reloadData()
        print(responseObject!.count)
       // print(self.items)
        let resultList = self.items["result"] as! [[String: 
 AnyObject]]
        print(resultList[5])
    }

    createCellHeightsArray()
    self.tableView.backgroundColor = UIColor(patternImage: 
  UIImage(named: "background")!)


}

// MARK: configure
func createCellHeightsArray() {
    for _ in 0...kRowsCount {
        cellHeights.append(kCloseCellHeight)
    }
}

// MARK: - Table view data source

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

override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {

    guard case let cell as DemoCell = cell else {
        return
    }

    cell.backgroundColor = UIColor.clearColor()

    if cellHeights[indexPath.row] == kCloseCellHeight {
        cell.selectedAnimation(false, animated: false, completion:nil)
    } else {
        cell.selectedAnimation(true, animated: false, completion: nil)
    }

    cell.number = indexPath.row
}


// with as! the cell is set to the custom cell class: DemoCell
// afterwards all data can be loaded in this method
override func tableView(tableView: UITableView, cellForRowAtIndexPath    
indexPath: NSIndexPath) -> UITableViewCell {
    let cell = 
tableView.dequeueReusableCellWithIdentifier("FoldingCell", 
forIndexPath: indexPath) as! DemoCell

//TODO: set all custom cell properties here (retrieve JSON and set in 
cell), use indexPath.row as arraypointer

//    let resultList = self.items["result"] as! [[String: AnyObject]]
 //   let itemForThisRow = resultList[indexPath.row]
//  cell.schoolIntroText.text = itemForThisRow["name"] as! String

    cell.schoolIntroText.text = "We from xx University..."
    return cell
}

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return cellHeights[indexPath.row]
}

// MARK: Table vie delegate

override func tableView(tableView: UITableView, 
didSelectRowAtIndexPath indexPath: NSIndexPath) {

    let cell = tableView.cellForRowAtIndexPath(indexPath) as! 
FoldingCell

    if cell.isAnimating() {
        return
    }

    var duration = 0.0
    if cellHeights[indexPath.row] == kCloseCellHeight { // open cell
        cellHeights[indexPath.row] = kOpenCellHeight
        cell.selectedAnimation(true, animated: true, completion: nil)
        duration = 0.5
    } else {// close cell
        cellHeights[indexPath.row] = kCloseCellHeight
        cell.selectedAnimation(false, animated: true, completion: 
nil)
        duration = 0.8
    }

    UIView.animateWithDuration(duration, delay: 0, options: 
.CurveEaseOut, animations: { () -> Void in
        tableView.beginUpdates()
        tableView.endUpdates()
        }, completion: nil)


}    
}

I get this result in JSON which is correct

{
 result =     (
            {
        city = Perth;
        "cou_id" = AU;
        environment = R;
        image = "-";
        name = "Phoenix English";
        rating = 0;
        "sco_id" = 2;
        "sco_type" = LS;
    },
            {
        city = "Perth ";
        "cou_id" = AU;
        environment = L;
        image = "-";
        name = "Milner college";
        rating = 0;
        "sco_id" = 3;
        "sco_type" = LS;
    },

what do I have to do to set these values and set them here?

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("FoldingCell", forIndexPath: indexPath) as! DemoCell
    //TODO: set all custom cell properties here (retrieve JSON and set in cell), use indexPath.row as arraypointer

    cell.schoolIntroText.text = "We from xx University..."
    return cell
}

I somehow dont figure out how to construct an array from this JSON output and how to access these fields which seem to be nested in many dimensions, as a noob, thx for any inputs.

Addition from class restApi:

// working method for calling api
func makeCall(completionHandler: (NSDictionary?, NSError?) -> ()) {

    Alamofire.request(
        .GET,
        baseURL+schools+nonAcademicParameter,
        headers: accessToken
        )
        .responseJSON { response in
            switch response.result {
            case .Success(let value):
                completionHandler(value as? NSDictionary, nil)
            case .Failure(let error):
                completionHandler(nil, error)
            }
    }
}

2 Answers 2

1

At your TODO point:

let resultList = self.items["result"] as! [[String: AnyObject]]
let itemForThisRow = resultList[indexPath.row]
cell.cityLabel.text = itemForThisRow["city"] as! String
cell.nameLabel.text = itemForThisRow["name"] as! String
...

To make dealing with json easier in swift try SwiftyJSON.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, but the line let resultList = self.items["result"] as! [[String: AnyObject]] gives an error stating: Thread 1: EXEC_BAD_INSTRUCTION.... and in the log: fatal error: unexpectedly found nil while unwrapping an Optional value. Any ideas why this is the case?
Does your json have the top level element named 'result'?
I don't know exactly what the top level element is. From my JSON response, "result" is just at the beginning once: result = ({array 1},{array 2},etc.. thx for your help
If i run this code snippet in viewDidLoad, it works and the data get parsed correctly. It seems to me that the cells want to load it before the result call has been returned. Could that be the problem? I edited my question and uploaded the whole class of UItableview.
0

I figured it out now. The size of the inner resultList array needs to be passed in numberOfRowsSelection. Then it loads the cell dynamically.

override func tableView(tableView: UITableView, numberOfRowsInSection    
section: Int) -> Int {
    print("size of self.resultlist.count: ")
    print(self.resultList.count)

    //size of the inner array with all the acutal values have to be 0 
at the beginning. when the async call comes back with the whole 
result, it will be updated. so it has to be set to the size of the 
array

//http://www.unknownerror.org/opensource/Alamofire/Alamofire/q/stackoverflow/29728221/uitableview-got-rendered-before-data-from-api-returned-using-swiftyjson-and-alam

    return self.resultList.count
}

1 Comment

Did you face any auto layout issue ? i am using swift3.0 with current git version. I am getting data from APi, but when i change anything like, create new iboutlet, and connect. the screen become dissapear. But when i click it shows folding cell. :(

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.