Francisco Romero
Francisco Romero

Reputation: 13199

How to get the number of rows from a request in tableView method?

I am using a tableViewController on my Swift 3.0 project. I want to get the number of rows of my tableview from a request and I am using Alamofire 4.0 for that purpose.

I saw that to return values from Alamofire you have to set a completionHandler (How to return value from Alamofire) but Xcode do not let me set it on tableView method.

This is the code that I have tried with set/get methods:

var numRows = 0

func setRows(numRows : Int){
    self.numRows = numRows
}

func getRows() -> Int{
    return self.numRows
}

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

    var JSON = [[String : AnyObject]]()

    Alamofire.request(url!, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: nil).responseJSON { response in

        switch(response.result) {
            case .success(_):
                JSON = response.result.value as! [[String : AnyObject]]!
                self.setRows(numRows: JSON.count)
                break

            case .failure(_):
                print("Error")
                break
        }
    }

    return self.getRows()
}

but I am not able to make it work. I know that Alamofire request is asynchronous and is the problem that I am facing but I am not able to set completionHandler on tableView function.

P.S: I also have tried to make synchronous Alamofire (making an asynchronous alamofire request synchronous) but completion block again appears and I am not able to set it to tableView method (I do not know if it is possible to set it on that method or I am doing it in the wrong way).

I have tried adding completion:(Int) -> Void to my tableView method but Xcode does not allow me to do that.

What should I do to set the number of rows after doing the request?

Thanks in advance!

Upvotes: 2

Views: 1366

Answers (3)

Oleg Gordiichuk
Oleg Gordiichuk

Reputation: 15512

This is the small example how it is possible to do.

Firstly create property of the rows and set init value that is 0 for example :

var rowCount = 0

After that create an elegant function that will fetch data and update rowCount,also this function will update our tableview example :

func elegantFuntionToUpdateRowCount() {
    var JSON = [[String : AnyObject]]()

Alamofire.request(url!, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: nil).responseJSON { response in

    switch(response.result) {
        case .success(_):
            JSON = response.result.value as! [[String : AnyObject]]!
            rowCount = JSON.count
            tableView reloadData
            break

        case .failure(_):
            print("Error")
            break
    }
}
}

And implement numberOfRowsInSection.

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

It is small example how it is possible to do but try to read a bit about software architecture.

Upvotes: 0

Lu_
Lu_

Reputation: 2685

I'm doing something like this:

table of items that will be in tableView

var positionsTable = [[String : AnyObject]]()

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

from request i get items and reload tableView

Alamofire.request(.GET, url, headers: headers, encoding: .JSON)
      .responseJSON { (response) in
          print(response)
          self.positionsTable = response.result.value
          self.tableView.reloadData()
     }
 }

Upvotes: 3

Simon McLoughlin
Simon McLoughlin

Reputation: 8465

You are thinking about this the wrong way. You don't need to set the completionHandler on the tableView.

The viewController's job is to control the flow of information.

  • Make your viewController conform to the tableView delegate methods.
  • Implement all the callback functions.
  • Have your viewController invoke the alamofire code to perform the async request.
  • Have the viewController process the completion block.
  • When processed, call "tableView.reloadData()" to call all the delegate methods again.

This will cause the tableView to request the number of rows again, and update the entire tableView's contents.

Also note that when dealing with UI, you should always use async networking methods. Your UI should make the user aware that something is processing, and then update the screen when its done.

Upvotes: 2

Related Questions