How to show data in tableview using Alamofire and swift3? - ios

I got the following response array of values:
["Mallard Point Trailer Court","Golddust","Hagler","McCosh Mill","Graystone","Old Jonesboro","Carlees Mobile Home Court","Denson","Blake","Inverness Cliffs"]
How to load this data in my tableview by using alamofire?
Here is my code
let url = Constants.CityUrl + fullName
print(url)
Alamofire.request(url, method: .get).responseJSON { response in
if let JSON = response.result.value {
print("JSON: \(JSON)")
let response = JSON as! NSArray
}

Inorder to access the array in whole class you need to declare it global like below, also prefer swift "Array" over "NSArray", As it has many advantages
var reponseArray = [String]
Also call below method from viewDidLoad
func fetchInformation() {
let url = Constants.CityUrl + fullName
print(url)
Alamofire.request(url, method: .get).responseJSON { response in
if let JSON = response.result.value {
print("JSON: \(JSON)")
reponseArray = JSON as! Array
DispatchQueue.main.async {
tableView.reloadData()
//reload on main thread
}
}
}
In Table View Data source method use information from reponseArray

Add one variable outside the completion block and assign the response to it.
For example:
let arrResponse: [String]?
In tableView delegate methods
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrResponse.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell
cell.textLabel?.text = arrResponse[indexPath.row] as! String
return cell
}

Related

UITableView and Cells from Model Array

I'm stuck on something I don't quite understand as from a few tests, it looks like the generation of table cell is happening before but not as well after a page load and Alamofire request.
If you see below I'm trying to get it to where our museum's outbound shipments are viewed after referencing the pro:
import Alamofire
import SwiftyJSON
class ShipmentProSearchResultsTableViewController: UITableViewController {
var pronumber:String = ""
var shipments = [Shipment]()
typealias JSONStandard = [String: AnyObject]
override func viewDidLoad() {
super.viewDidLoad()
fetchShipments()
}
func fetchShipments() {
let parameters: Parameters = ["pro_number": pronumber]
let todoEndpoint: String = "OURHOST/shipments/api/details/pro"
Alamofire.request(todoEndpoint, method: .get, parameters: parameters)
.responseJSON { response in
if response.result.isSuccess{
let shipmentJSON : JSON = JSON(response.result.value!)
for (index, subJson):(String, JSON) in shipmentJSON{
let proNumber = subJson["proNumber"].int
let consigneeName = subJson["consignee"]["name"].string
let shipment = Shipment(proNumber: proNumber!, consigneeName: consigneeName!)
self.shipments.append(shipment)
}
print(self.shipments)
}else{
print("Could not get results")
}
}
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return shipments.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ShipmentCell", for: indexPath)
let shipment = shipments[indexPath.row]
cell.textLabel?.text = "Hello"
cell.detailTextLabel?.text = "\(shipment.proNumber)"
return cell
}
}
Now where I printed the self.shipments, I get the following results:
[OakRidgeArchaeologicalRepositoryDispatcher.Shipment(proNumber: 471008276, consigneeName: "A1 CHICAGO INSTITUTE OF THE ARTS")]
So I know the data is appropriately being passed to the model. I will also note that the Table View Cell Identifier in the storyboard is correctly set to ShipmentCell. But after the query, nothing pops up in my table.
I'm using Swift 4.
You should reload the tableView after updating source field.
func fetchShipments() {
let parameters: Parameters = ["pro_number": pronumber]
let todoEndpoint: String = "OURHOST/shipments/api/details/pro"
Alamofire.request(todoEndpoint, method: .get, parameters: parameters)
.responseJSON { response in
if response.result.isSuccess{
let shipmentJSON : JSON = JSON(response.result.value!)
for (index, subJson):(String, JSON) in shipmentJSON{
let proNumber = subJson["proNumber"].int
let consigneeName = subJson["consignee"]["name"].string
let shipment = Shipment(proNumber: proNumber!, consigneeName: consigneeName!)
self.shipments.append(shipment)
}
tableView.reloadData() //<-------add this.
print(self.shipments)
}else{
print("Could not get results")
}
}
}

UITableView Delegate functions execute before data source can be retrieved from database - SWIFT?

I am trying to load some data into UITableView from a database but the delegate functions used to populate the tableView executes and returns an empty table before I have had a chance to retrieve the data to be displayed in tableView?
Please can someone advise?
Here is my code:
var arrayOptions = [String]()
override func viewDidLoad() {
super.viewDidLoad()
print("MenuOptions viewDidLoad ...")
getArrayOfOptionsForMenu()
}
private func getArrayOfOptionsForMenu(){
// Get list of menu options and populate array
// Construct parameters to send to server
var parameter = [String:String]()
parameter["getoptions"] = "formenu"
let optionsURL = LabBookAPI.getCredentialsUrl(parameters: parameter, targetUrl: "getOptions.php?")
var request = URLRequest.init(url: optionsURL)
request.httpMethod = "POST"
let task = session.dataTask(with: request) { (data, response, error) in
if let jsonData = data{
do{
let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: [])
print("jsonObject: \(jsonObject)")
guard
let myArray = jsonObject as? [String] else{
print("data not in [String] format")
return
}
DispatchQueue.main.async{
self.arrayOptions = myArray
print("self.arrayOptions.count: \(self.arrayOptions.count)")
}
}catch let error{
print("print error: \(error)")
}
}else if let requestError = error{
print("error detail: \(requestError)")
}else{
print("unexpected error")
}
}// End task
task.resume()
}// End of function
/* DELEGATE FUNCTIONS */
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("numberOfRowsInSection self.arrayOptions.count: \(self.arrayOptions.count)")
return self.arrayOptions.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("cellForRowAt self.arrayOptions.count: \(self.arrayOptions.count)")
let cell = UITableViewCell.init(style: .value1, reuseIdentifier: "optionCell")
cell.textLabel?.text = self.arrayOptions[indexPath.row]
print("self.arrayOptions[indexPath.row]: \(self.arrayOptions[indexPath.row])")
return cell
}
My console:
viewDidLoad ... NSDataPDFDocument: nil MenuOptions viewDidLoad ...
MenuOptions viewWillAppear ... numberOfRowsInSection
self.arrayOptions.count: 0 numberOfRowsInSection
self.arrayOptions.count: 0 numberOfRowsInSection
self.arrayOptions.count: 0 jsonObject: (
Profile,
"Sign out" ) self.arrayOptions.count: 2
Your data is fetched from the network which takes some time to do. Rendering the TableView doesn't need to wait around.
We call these longer tasks Asynchronous tasks, they run in the background and the app continues doing other things until we get a response.
All you need to do is tell the TableView to reload the data when you get your response
DispatchQueue.main.async {
self.arrayOptions = myArray
self.tableView.reloadData()
}
EDIT:
I think you are using a UITableViewController which already contains a UITableView property, so you can use self.tableView. If you aren't using a UITableViewController then you need to create an outlet and set self.tableView.dataSource = self and self.tableView.delegate = self
You just need to reload table data:
DispatchQueue.main.async{
self.arrayOptions = myArray
print("self.arrayOptions.count: \(self.arrayOptions.count)")
self.tableView.reloadData()
}

How to show Api response in tableview cell in swift

I am stuck in my code, I am trying show to API response tableview cell but i have not any idea how to fill data in array ,So not showing anything in my tableviewcell. I am using custome cell and Alamofire in swift. Please improve my mistake give me solution .
func Api_call()
{
let url = URL(string: "https://dousic.com/api/radiolist")!
let components = URLComponents(url: url, resolvingAgainstBaseURL: true)!
// let fragment = components.fragment!
print(components)
let params = ["user_id":"16" ]
Alamofire.request(url, method: .post, parameters: params, encoding: URLEncoding.default).responseJSON {response in
self.hideActivityIndicator()
var err:Error?
switch response.result {
case .success(let value):
print(value)
let json = JSON(value)
// returns nil if it's not an array
if let resData = json["radioList"].arrayObject
{
self.array_RadioList = resData as! [[String:AnyObject]]
}
if self.array_RadioList.count > 0 {
self.tbl_home.reloadData()
}
case .failure(let error):
err = error
print(err ?? "error .....")
}
}
}`
Thanks for help .
EDIT
Just create a radio list variable like this
var array_RadioList:[JSON]?
Get array from json like this
-
if let resData = json["response"]["radioList"].array {
self.array_RadioList = resData
self.tableView.reloadData()
}
and reload data.And get radio object in
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: UITableViewCell? = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier)
let radio:JSON? = array_RadioList?[indexPath.row]
cell?.textLabel?.text = radio?["radio_tags"].string
return cell ?? UITableViewCell()
}
If you are getting your array_RadioList from Api_call(), try this
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : homeCell = tableView.dequeueReusableCell(withIdentifier: "homeCell")! as! homeCell
cell.lbl_name?.text = array_RadioList[indexPath.row]["radio_title"] as? String
return cell
}
and also check for numberOfRowsInSection function.
If the API you're calling is well-made, you should use a get method, not a post.
Also, I tried to use "https://dousic.com/api/radiolist?user_id=16" but it return
{
"response": {
"code": "301",
"error": "wrong url"
}
}
These 2 things could be your problem, or it could be in your custom cells, or in you cellforrow method...
If you can show more code it would help.
EDIT
Try to use this version of the optional chaining :
if let resData = json["radioList"].arrayObject as? [[String:AnyObject] {
self.array_RadioList = resData
self.tbl_home.reloadData()
}
and try to debug it with breakpoints to see if the application goes everywhere you want and what are your variables at this time.
Try this
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return [self.array_RadioList].count;
}

Unable to append strings to array while parsing JSON data

I am having difficulties storing the results retrieved from a JSON source data. I have confirmed the ability to print the data retrieved but it was not able to store into my local array.
My end objective is to actually print in a UITableView the results.
Below is the code for my relevant table view controller :
import UIKit
class CommunityActivityTableViewController: UITableViewController {
var displayNameArr = [String]()
var postDateArr = [String]()
var postDetailArr = [String]()
var testArr = ["teaad"]
override func viewDidLoad() {
super.viewDidLoad()
parseJson()
print(self.displayNameArr.count) //returns 0
print(self.postDateArr.count) //returns 0
print(self.postDetailArr.count) //returns 0
print(self.testArr.count)
print("end")
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return self.displayNameArr.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
print("3")
let cell = tableView.dequeueReusableCellWithIdentifier("Cell_activity", forIndexPath: indexPath)
print("hi")
cell.textLabel?.text = "hi"
cell.detailTextLabel?.text = "test"
return cell
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func makeAttributedString(title title: String, subtitle: String) -> NSAttributedString {
let titleAttributes = [NSFontAttributeName: UIFont.preferredFontForTextStyle(UIFontTextStyleHeadline), NSForegroundColorAttributeName: UIColor.purpleColor()]
let subtitleAttributes = [NSFontAttributeName: UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline)]
let titleString = NSMutableAttributedString(string: "\(title)\n", attributes: titleAttributes)
let subtitleString = NSAttributedString(string: subtitle, attributes: subtitleAttributes)
titleString.appendAttributedString(subtitleString)
return titleString
}
func parseJson(){
//MARK: JSON parsing
let requestURL: NSURL = NSURL(string: "<sanitised>")!
let urlRequest: NSMutableURLRequest = NSMutableURLRequest(URL: requestURL)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(urlRequest) {
(data, response, error) -> Void in
let httpResponse = response as! NSHTTPURLResponse
let statusCode = httpResponse.statusCode
if (statusCode == 200) {
print("Everyone is fine, file downloaded successfully.")
do{
let json = try NSJSONSerialization.JSONObjectWithData(data!, options:.AllowFragments)
if let results = json["result"] as? [[String: AnyObject]] {
for result in results {
if let lastname = result["last_name"] as? String {
if let postdate = result["timestamp"] as? String {
if let firstname = result["first_name"] as? String {
if let postdetails = result["post_details"] as? String {
let displayname = firstname + " " + lastname
//print(displayname)
self.displayNameArr.append(displayname)
self.postDateArr.append(postdate)
self.postDetailArr.append(postdetails)
self.testArr.append("haha")
}
}
}
}
}
}
}catch {
print("Error with Json: \(error)")
}
}
}
task.resume()}
}
As per the code above the print results of displaynamearr.count and postDateArr.count and postDetailArr.count returned 0 when it should have returned more than 0 as a result of parseJson() method.
I have printed the display name, postgame and post details variables and they all contain data within so the problem does not lie with the extraction of data but the appending of data into the array.
Appreciate any help provided thanks ! Developed on Xcode 7 and Swift 2.2
Sanitised my JSON source due to sensitive nature of information (i have verified the retrieval of information is OK)
dataTaskWithRequest() is an asynchronous data loading. It loads on the background thread ensuring your UI won't freeze up. So your array will be empty when you this will be getting executed and hence your error. You need to a completion handler like so:
func parseJson(completion: (isDone: Bool) -> ()){
///code
for result in results {
if let lastname = result["last_name"] as? String {
if let postdate = result["timestamp"] as? String {
if let firstname = result["first_name"] as? String {
if let postdetails = result["post_details"] as? String {
let displayname = firstname + " " + lastname
//print(displayname)
self.displayNameArr.append(displayname)
self.postDateArr.append(postdate)
self.postDetailArr.append(postdetails)
self.testArr.append("haha")
}
completion(isDone: True)
}
}
Now in viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
parseJson(){ success in
if success{
print(self.displayNameArr.count) //returns a value
print(self.postDateArr.count) //returns a value
print(self.postDetailArr.count) //returns a value
print(self.testArr.count) //This wont because I havent added it in the completion handler
print("end")
self.tableView.reloadData()
}
}
}
All of your UI updates run on the main thread. If you do something like
let task = session.dataTaskWithRequest(urlRequest) {
(data, response, error) -> Void in
// ...
}.resume()
you start a task asynchronously on another thread (not the main thread). Your iPhone is doing a network request and this takes some time. So I guess when your cellForRowAtIndexPath delegate method is called you haven't received any data yet. This is the reason you don't see anything.
The easiest solution to this would be to reload the table view once you have received the data. When you're done with all the parsing in your parseJson method (outside of all the loops) simply run:
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
}
This forces your table view to update. Remember that you have to run code that updates the UI on the main thread. This is what dispatch_async(dispatch_get_main_queue()) {} does.
EDIT: The answer above was to illustrate the problem to you. The more elegant solution would be to use a completion handler like so:
func parseJson(completionHandler: (Bool) -> Void) {
//do all your json parsing.
//....
dispatch_asyc(dispatch_get_main_queue()) {
//run this if you received the data
//implement some kind of if statement that checks if the parsing was successful
completionHandler(true)
//run this if it failed
completionHandler(false)
}
}
In your viewDidLoad you would do something like
override func viewDidLoad() {
super.viewDidLoad()
//...
parseJson() { success in
tableView.reloadData()
if(success) {
print("success")
}
}
}
If you want to display an activity indicator while data is loaded (which I would recommend) it is easier to use a callback as I've just described.

Dynamically populating an iOS table view with Swift from an API

I'm currently in the process of creating an app to display the latest football scores. I've connected to an API through a URL and pulled back the team names for the english premier league into an array of strings.
The problem seems to come from populating the iOS table view that I intend to display the list of teams with. The data appears to be pulled from the API fine, but for some reason the TableView method which creates a cell and returns it doesn't seem to be called. The only time I can get the method to be called is when I actually hard code a value into the array of team names.
Here is my code:
class Main: UIViewController {
var names = [String]()
override func viewDidLoad() {
super.viewDidLoad()
let URL_String = "https://football-api.com/api/?Action=standings&APIKey=[API_KEY_REMOVED]&comp_id=1204"
let url = NSURL(string: URL_String)
let urlRequest = NSURLRequest(URL: url!)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config)
let task = session.dataTaskWithRequest(urlRequest, completionHandler: {
(data, response, error) in
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments)
if let teams = json["teams"] as? [[String : AnyObject]] {
for team in teams {
if let name = team["stand_team_name"] as? String {
self.names.append(name)
}
}
}
} catch {
print("error serializing JSON: \(error)")
}
})
task.resume()
}
// Number of Sections In Table
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
// Number of Rows in each Section
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return names.count
}
// Sets the content of each cell
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
cell.textLabel?.text = names[indexPath.row]
return cell
}
}
Just wondering if anyone can point me in the right direction here. This code doesn't crash or throw any errors, it just refuses to load a table view. The only reason I can possibly think of is that the array of team names is empty after completing a request to the API. However I've set breakpoints throughout and checked the values of local variables and the desired information is being pulled from the API as intended...
you are in the correct way , just refresh the table using reloadData once you got the new data from API
if let teams = json["teams"] as? [[String : AnyObject]] {
for team in teams {
if let name = team["stand_team_name"] as? String {
self.names.append(name)
}
}
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.yourtableViewname.reloadData()
})
}

Resources