Kushal Jogi
Kushal Jogi

Reputation: 285

UITableView does not display the cells (using swift )

I am using xcode v6.4. I want to display all the names of the users that I get from AWS DynamoDB in to a table view. I tried the following code

import UIKit
class messagesTableViewController: UITableViewController {

var myData: Array<AnyObject> = []
override func viewDidLoad() {
    super.viewDidLoad()


    let exp = AWSDynamoDBScanExpression()

    //  exp.valueForKey("name")
    //    exp.scanFilter = [ "date" : cond ]

    self.scan(exp).continueWithSuccessBlock({ (task: AWSTask!) -> AWSTask! in
        NSLog("Scan multiple values - success")
        let results = task.result as! AWSDynamoDBPaginatedOutput
        for r in results.items {
            let myItem: Item = r as! Item

            println(myItem.name)
            self.myData.append(myItem.name)

            println("\(self.myData)")

        }
        return nil
    })
}

func scan(expression : AWSDynamoDBScanExpression) -> AWSTask! {

    let mapper = AWSDynamoDBObjectMapper.defaultDynamoDBObjectMapper()
    return mapper.scan(Item.self, expression: expression)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    // #warning Potentially incomplete method implementation.
    // Return the number of sections.
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete method implementation.
    // Return the number of rows in the section.
    println("\(myData.count)")
    return myData.count

}


override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cellID: String = "cell"
    var cell = tableView.dequeueReusableCellWithIdentifier(cellID) as! inboxTableViewCell
    dispatch_async(dispatch_get_main_queue(), {


        cell.nameLabel.text = self.myData[indexPath.row] as? String

    })



    return cell

}

Here, the print command 'println("(self.myData)")' prints the proper data but the same data does not get displayed on the table view.

Also, the same code works properly and displays the cells in table view when I add static values to an Array. For example, below is my code:

import UIKit

class messagesTableViewController: UITableViewController {


var myDummy: Array<AnyObject> = []

override func viewDidLoad() {
    super.viewDidLoad()

    var i = 1
    myDummy = ["Amit", "Kushal", "Saurabh", "Harsh", "Swar"]

 }   



override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    // #warning Potentially incomplete method implementation.
    // Return the number of sections.
    return 1
}

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

    return myDummy.count

}


override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cellID: String = "cell"
    var cell = tableView.dequeueReusableCellWithIdentifier(cellID) as! inboxTableViewCell
    dispatch_async(dispatch_get_main_queue(), {


        cell.nameLabel.text = self.myDummy[indexPath.row] as? String

    })



    return cell

}

It will be a great help if somebody can guide me through this.

Upvotes: 3

Views: 4353

Answers (3)

Kushal Jogi
Kushal Jogi

Reputation: 285

I figured it out finally. Here is the updated code.

import UIKit

class messagesTableViewController: UITableViewController {

var myData: Array<AnyObject> = []


override func viewDidLoad() {
    super.viewDidLoad()

    var i = 1

    let exp = AWSDynamoDBScanExpression()

    //  exp.valueForKey("name")
    //    exp.scanFilter = [ "date" : cond ]

    self.scan(exp).continueWithSuccessBlock({ (task: AWSTask!) -> AWSTask! in
        NSLog("Scan multiple values - success")
        let results = task.result as! AWSDynamoDBPaginatedOutput
        for r in results.items {
            let myItem: Item = r as! Item

            println(myItem.name)
            self.myData.append(myItem.name)

            println("\(self.myData)")

        }

  // This is the change in code. It needs to be added because the AWS scan  gathers the data in a background queue and we need to get back to the main queue after the background task is completed and then reload the table view.
        dispatch_async(dispatch_get_main_queue(), {
            self.tableView.reloadData()
        });
        return nil
    })

}

func scan(expression : AWSDynamoDBScanExpression) -> AWSTask! {

    let mapper = AWSDynamoDBObjectMapper.defaultDynamoDBObjectMapper()
    return mapper.scan(Item.self, expression: expression)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    // #warning Potentially incomplete method implementation.
    // Return the number of sections.
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete method implementation.
    // Return the number of rows in the section.
    println("\(myData.count)")
    return myData.count

}


override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cellID: String = "cell"
    var cell = tableView.dequeueReusableCellWithIdentifier(cellID) as! inboxTableViewCell
    dispatch_async(dispatch_get_main_queue(), {


        cell.nameLabel.text = self.myData[indexPath.row] as? String

    })



    return cell

}



}

The code in the question did not work because AWS scan gathers the data in a background queue and we need to get back to the main queue after the background task is completed and then reload the table view.

Upvotes: 3

user5032033
user5032033

Reputation:

Try removing the dispatch_async part and change nameLabel to textLabel, like this:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell = tableView.dequeueReusableCellWithIdentifier("cell") as! inboxTableViewCell


    cell.textLabel.text = self.myDummy[indexPath.row] as? String



    return cell

}

Upvotes: 0

Manav Gabhawala
Manav Gabhawala

Reputation: 997

Here's the code that should work:

override func viewDidLoad() {
    super.viewDidLoad()
    let exp = AWSDynamoDBScanExpression()

    self.scan(exp).continueWithSuccessBlock({ (task: AWSTask!) -> AWSTask! in
    println("Scan multiple values - success")
    let results = task.result as! AWSDynamoDBPaginatedOutput
    for r in results.items {
        let myItem: Item = r as! Item

        println(myItem.name)
        self.myData.append(myItem.name)

     }
     // THIS IS THE CODE YOU NEED TO ADD:
     tableView.reloadSections(NSIndexSet(index: 0), withRowAnimation: UITableViewRowAnimation.Automatic) // Or choose some other animation.
     return nil
  })
}

Upvotes: 0

Related Questions