In my app I have two table views. The first table view has a set number of cells.
These cells will always be the same and will never change.
See below:
The above table view will always have the 3 cells and never more.
On my server I have my API which has routes for each of these cells.
For example:
GET - myAPI/game
GET - myAPI/book
GET - myAPI/travel
And each routes send backs different data.
What I am trying to do is that when a user clicks on a table view cell it takes them to a new table view whose cells contain the response from the API.
Currently my 2ND table view is empty see below:
This is what I have tried so far:
import UIKit
class SectorListTableViewController: UITableViewController {
struct WeatherSummary {
var id: String
}
var testArray = NSArray()
var manuArray = NSArray()
// Array of sector within our company
var selectSector: [String] = ["Game", "Book","Travel"]
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.rowHeight = 80.0
var weatherArray = [WeatherSummary]()
var request = NSMutableURLRequest(URL: NSURL(string: "myAPI")!)
var session = NSURLSession.sharedSession()
request.HTTPMethod = "GET"
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
//var params = ["email":"\(emailAdd)", "password":"\(pass)"] as Dictionary<String, String>
var err: NSError?
//request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
println("Response: \(response)")
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: \(strData)")
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSArray
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
// Did the JSONObjectWithData constructor return an error? If so, log the error to the console
if(err != nil) {
println(err!.localizedDescription)
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: '\(jsonStr)'")
}
else {
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
// The JSONObjectWithData constructor didn't return an error. But, we should still
// check and make sure that json has a value using optional binding.
var newWeather = WeatherSummary(id:"")
if let parseJSON = json {
for weather in parseJSON {
if let id = weather["employeeName"] as? String{
println(" LOOK HERE \(id)")
newWeather.id = id
}
}
weatherArray.append(newWeather)
self.testArray = parseJSON
}
else {
// Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonStr)")
}
}
})
task.resume()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
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.
return self.selectSector.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("sectorList", forIndexPath: indexPath) as! UITableViewCell
// Configure the cell...
if selectSector.count > 0 {
cell.textLabel?.text = selectSector[indexPath.row]
}
return cell
}
/*
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return NO if you do not want the specified item to be editable.
return true
}
*/
/*
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
// Delete the row from the data source
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
} else if editingStyle == .Insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return NO if you do not want the item to be re-orderable.
return true
}
*/
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
if let destination = segue.destinationViewController as? BioListTableViewController {
let indexPath = self.tableView.indexPathForSelectedRow()
if let row:Int = indexPath?.row {
destination.bioArray = testArray
}
}
}
}
BIO LIST VIEW CONTROLLER CLASS CODE:
import UIKit
struct Note {
var name:String
var job:String
}
class BioListTableViewController: UITableViewController {
private var notes = Array<Note>()
var bioArray = NSArray()
var name = String()
var weather = NSArray()
override func viewDidLoad() {
super.viewDidLoad()
println("THIS IS BIO ARRAY COUNT\(bioArray.count)")
//var weather:WeatherSummary?
var newItem:Note = Note(name: "", job: "")
for x in bioArray {
if let id = x["employeeName"] as? String{
newItem.name = id
}
}
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
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.
return self.bioArray.count ?? 0
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("bioCell", forIndexPath: indexPath) as! UITableViewCell
// Configure the cell...
// cell.textLabel?.text = "test"
let weatherSummary: AnyObject = bioArray[indexPath.row]
if let id = weatherSummary["employeeName"] as? String //Dont know the exact syntax.
{
cell.textLabel?.text = id
}
if let job = weatherSummary["jobTitle"] as? String {
cell.detailTextLabel?.text = job
}
return cell
}
}
UPDATE:
This is what is being returned from testArray.
The reason why you couldn't make your API calls work on cell selection is simple.
These are asynchronous calls. Which means that they will return at some point, but not necessarily soon. In fact, the design which you have now is also bad because if your internet connection is slow it might take a long time before your API loads.
Here is what you should do.
In your BioListTableViewController create a variable which will identify which API needs to be called (maybe it is worth making it an enum):
enum NeededAPI {
case Game
case Book
case Travel
case None
}
class BioListTableViewController: UITableViewController {
var apiThatNeedsToBeCalled:NeededAPI = .None {
didSet {
//check which API is set and call the function which will call the needed API
}
}
var bioArray = NSArray() {
didSet {
self.tableView.reloadData()
}
}
What you have to do now is to move API calling logic to the BioListTableViewController. When user selects cell you set the correct value for the apiThatNeedsToBeCalled. Once you do this, code inside the didSet will get executed and it should call the function which calls the appropriate API.
This function is an asynchronous one so it will return whenever it finishes. When it returns, you set
self.bioArray = results
which triggers
self.tableView.reloadData()
Obviously, you need an IBOutlet for your tableView.
Create an IBOutlet for tableView and then call tableView.reloadData() inside viewWillAppear method, and make sure tableView delegate and dataSource are set to viewController and testArray have some objects.
But I have seen some fundamental issue in your code, you should architect your code in a way when user selects some option after that you should load data from server and it would be better if you load that data inside detailVC, at the moment you are loading data in master and even before any user interaction in viewDidLoad method which I think not right. may be use never select any option and in that case you are consume user data, you should also think about that, and also it will consume memory.
What should you do: pass user select option to detailVC i.e BioListVC in your case, and in side that in setter method or viewWillAppear fireOff data loading call in background and show a spinner and when you have data set it to dataSource array and call reload method on main thread.
Check if your data have been downloaded correct before your cell was clicked, which means self.testArray not nil.
EDIT:
You can use a global NSMutableDictionary property like testArray, then make 3 api calls to get the 3 different datas:
NSMutableDictionary *testDictionary = [NSMutableDictionary new];
[testDictionary setValue:testArray1 forKey:#"books"];
[testDictionary setValue:testArray2 forKey:#"travels"];
[testDictionary setValue:testArray3 forKey:#"anykeys"];
And in your segue, use [testDictionary valueForKey:#"books"]
Related
I am exporting json file from itunes api>converted that to a json file>send that to firebase> brought that in to a dictionary file here and now I am trying to put that into a tableview but it does not seem to work and I have no clue why. I checked that:
1. The file that I imported was successfully converted into a dictionary.
2. Datasource and delegate is connected to this UITableViewController file.
3. Put other arrays to check if my connections were right(and it worked but it does not work at all if I use the data that I brought in with Firebase)
4. I put cell style as subtitle and type as dynamic.
Below is the UITableViewController code:
import UIKit
import Firebase
class TableViewController1: UITableViewController {
var ref: FIRDatabaseReference!
var rank = [String]()
var song = [[String]]()
var artist = [[String]]()
var tna = [String]()
override func viewDidLoad() {
super.viewDidLoad()
self.ref = FIRDatabase.database().reference()
let userID = FIRAuth.auth()?.currentUser?.uid
self.ref.child("top100itunes").observeSingleEvent(of: .value, with: { (snapshot) in
let jsonfile = snapshot.value! as! String
//print(jsonfile)
let jsondict:[String:Any] = self.convertToDictionary(text: jsonfile)!
for (key, value) in jsondict {
if key != nil {
self.rank.append(key)
if value != nil{
self.tna.append(value as! String)
}
}
}
for x in self.tna{
if x != nil {
for (key,value) in self.convertToDictionary(text: x)!{
self.song.append([key])
self.artist.append([value as! String])
}
}
}
}, withCancel: nil)
}
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
func convertToDictionary(text: String) -> [String: Any]? {
if let data = text.data(using: .utf8) {
do {
return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
} catch {
print(error.localizedDescription)
}
}
return nil
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return self.song.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return self.song[section].count
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.rank[section]
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath)
cell.textLabel?.text = self.song[indexPath.section][indexPath.row]
cell.detailTextLabel?.text = self.artist[indexPath.section][indexPath.row]
return cell
}
}
The json file that I imported is in the structure like:
{ 1 : { Title : Artist },
2 : { Title : Artist },
.....
}
observeSingleEvent() is asynchronous and numberOfRowsInSection() will be getting called before observeSingleEvent() has finished populating the data.
If you put a call to self.tableView.reloadData() after the 2nd for loop then this will cause a refresh of the table view once the data has been populated.
Alternatively you could consider re-architecting your app so it has a separate model component that is responsible for data retrieval so that the data could have been populated before the view is launched if applicable.
Your code is doing this:
viewDidLoad
start firebase async
ask for tableview number of sections/rows
song.count is 0
tableview loads with no cells
firebase async completes and populates song array
... nothing else
After this method you should add tableView reloadData like so:
for x in self.tna{
if x != nil {
for (key,value) in self.convertToDictionary(text: x)!{
self.song.append([key])
self.artist.append([value as! String])
}
}
}
self.tableView.reloadData()
I agree with Halfman that you should rearchitect your application to separate out the model from the controller. Read up on MVC.
I also suggest that instead of maintaining multiple arrays (i.e. song, artist, tna) you use a single struct to manage all this data. Read up on Swift structures.
TableViewController1 isn't an optimal choice for a controller name. Maybe SongListTableViewController is more clear?
A new programmer here. How would I populate my tableView from this JSON?
My first problem is the JSON Serialization and then plugging it in the tableView.
Code
import UIKit
class LegislatorsTableVC: UITableViewController {
// MARK: Variables & Outlets
private let cellIdentifer = "cellReuse"
// MARK: View Did Load
override func viewDidLoad() {
super.viewDidLoad()
// Creating Congfiguration Object // Session Is Created // Getting Info/Data
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: configuration)
let apiKey = "https://congress.api.sunlightfoundation.com/legislators?apikey=xxxxxxxxxxxxxxxxxxxxx&all_legislators=true&per_page=all"
if let url = NSURL(string: apiKey) {
// Spawning Task To Retrieve JSON Data
session.dataTaskWithURL(url, completionHandler: { (data, response, error) -> Void in
// Checking For Error
if let error = error {
print("The error is: \(error)")
return
}
// Response
if let httpResponse = response as? NSHTTPURLResponse where httpResponse.statusCode == 200, let data = data {
print("Status Code: \(httpResponse.statusCode)")
// self.JSONSerialization(data)
}
}).resume()
}
} // End Of View Did Load
// JSON Serialization Function With SwiftyJSON.swift
private func JSONSerialization(data: NSData){
// I See this Gets A Status Code 200 And Then I'm Lost.
do {
let json = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers) as! [String: AnyObject]
} catch {
print("Error Serializing JSON Data: \(error)")
}
} // End Of JSONSerialization
// MARK: - Table view data source
// Number Of Sections
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
} // End Of Number Of Sections
// Number Of Rows In Section
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 15
} // End Of Number Of Rows In Section
// Cell For Row At Index Path
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifer, forIndexPath: indexPath) as! LegislatorTVCell
// Configure the cell...
cell.name.text = "Name"
cell.title.text = "Title"
cell.party.text = "Party"
return cell
} // End Of Cell For Row At Index Path
}
Create a custom class Person outside the view controller
class Person {
var firstName = ""
var lastName = ""
var title = ""
var party = ""
}
Create an array of Person in the view controller
var people = [Person]()
The JSON has a key results which contains an array of dictionaries.
In viewDidLoad parse the JSON and create Person instances. Finally reload the table view.
override func viewDidLoad() {
super.viewDidLoad()
// Creating Congfiguration Object // Session Is Created // Getting Info/Data
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: configuration)
let apiKey = "https://congress.api.sunlightfoundation.com/legislators?apikey=xxxxxxxxxxxxxxxxxx&all_legislators=true&per_page=all"
if let url = NSURL(string: apiKey) {
// Spawning Task To Retrieve JSON Data
session.dataTaskWithURL(url, completionHandler: { (data, response, error) -> Void in
// Checking For Error
if error != nil {
print("The error is: \(error!)")
return
} else if let jsonData = data {
do {
let parsedJSON = try NSJSONSerialization.JSONObjectWithData(jsonData, options: []) as! [String:AnyObject]
guard let results = parsedJSON["results"] as? [[String:AnyObject]] else { return }
for result in results {
let person = Person()
person.firstName = result["first_name"] as! String
person.lastName = result["last_name"] as! String
person.party = result["party"] as! String
person.title = result["title"] as! String
self.people.append(person)
}
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
}
} catch let error as NSError {
print(error)
}
}
}).resume()
}
} // End Of View Did Load
The table view delegate methods look very clear when using a custom class.
Since cellForRowAtIndexPath is called very often the code is quite effective.
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return people.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifer, forIndexPath: indexPath) as! LegislatorTVCell
let person = people[indexPath.row]
cell.name.text = person.firstName + " " + person.lastName
cell.title.text = person.title
cell.party.text = person.party
return cell
} // End
Of course I couldn't test the code but this might be a starting point.
Basically what you want to do is introduce a new variable to your class, for example jsonDict like so:
class LegislatorsTableVC: UITableViewController {
var jsonDict:Dictionary<String,AnyObject>?
// further code
And then - you almost got it right already - save your JSON serialization into that in your JSONSerialization function. (which I would rename to parseJSON or something like that to avoid confusion) like so:
do {
jsonDict = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers) as! [String: AnyObject]
} catch {
print("Error Serializing JSON Data: \(error)")
}
So then you can return the right values to your tableView data source:
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return jsonDict["your JSON key"].count ?? 0
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return jsonDict["your JSON key"]["items"].count ?? 0
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifer, forIndexPath: indexPath) as! LegislatorTVCell
let item = jsonDict["your JSON key"][indexPath.row]
// Configure the cell...
cell.name.text = item["name"]
cell.title.text = item["title"]
cell.party.text = item["party"]
return cell
}
Naming is a little confusing, as I don't know the layout of your JSON, but replace your JSON key with your path to the data of course.
I did this for fetching data and showing it in a table view
but it's not showing anything.
I used this code:
import UIKit
import Parse
import Bolts
class Parsedata: UIViewController, UITableViewDelegate, UITableViewDataSource {
//#IBOutlet var NTableView: UITableView!
#IBOutlet var NTableView: UITableView!
var NArray:[String] = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.NTableView.delegate = self
self.NTableView.dataSource = self
// retrieve notification from parse
self.RetrieveN()
NSLog("Done with it")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func RetrieveN () {
//create a pfquery
var query:PFQuery = PFQuery(className: "Notification")
//call findobject in background
query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
//clear the Narray
self.NArray = [String]()
//loop through the objects array
for Nobject in objects!{
//retrieve the text column value of each PFobject
let Ntext:String? = (Nobject as! PFObject) ["Text"] as? String
// assign it into your Narray
if Ntext != nil {
self.NArray.append(Ntext!)
}
}
if error == nil {
// The find succeeded.
print("Successfully retrieved \(objects!.count) Notifications.")}
//reload the table view
self.NTableView.reloadData()
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.NTableView.dequeueReusableCellWithIdentifier("NCell") as UITableViewCell?
cell?.textLabel?.text = self.NArray[indexPath.row]
return cell!
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return NArray.count
}
}
It's working fine because it's showing that 3 objects were retrieved on the LOG container.
Unless you have more code than what's posted here, you also need to implement numberOfSectionsInTableView and return 1
I have just learnt how to do this myself, this is how you can load data from parse and save it as a NSMutableArray then use that data to populate your table view.
let NArray : NSMutableArray = NSMutableArray()
then you can use your query you made with
var query:PFQuery = PFQuery(className: "Notification")
query.findObjectsInBackgroundWithBlock( { (AnyObject objects, NSError error) in
if error == nil {
self.NArray = NSMutableArray(array: objects!)
self.NTableView.reloadData()
} else {
print(error?.localisedDescription)
})
this will load all your content into the variable NArray, which you can then use in your tableView function with indexPath. That line of code inside your tableView cellForRowAtIndexPath would be
cell?.textLabel?.text = self.NArray[indexPath.row] //you may have to cast this as? String
Like i said this is how i am loading my data, i am using this to load PFUser usernames, profile pictures etc and displaying them in a custom table view cell.
You may have to slightly tweak these methods but the base methods are there
I am using NSURL to get the source code of a website page. I am passing MySQL query instructions via the URL to interact with the database to get a list of a user's friends. Everything works well up to the point of adding the returned data to an array, to them be filed into a table view. The website's response prints to the terminal well, however if I add it to the array to be added to the table view, it is not recognized after the NSURl session is complete.
Code:
//
// viewFriendsViewController.swift
// collaboration
//
// Created by nick on 11/12/15.
// Copyright © 2015 Supreme Leader. All rights reserved.
//
import UIKit
class viewFriendsViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var textArray: NSMutableArray! = NSMutableArray()
func tableView(tableView: UITableView, numberOfRowsInSection Section: Int) -> Int {
return self.textArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell: UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell")! as UITableViewCell
cell.textLabel?.text = self.textArray.objectAtIndex(indexPath.row) as? String
return cell
}
override func viewWillAppear(animated: Bool) {
let username = NSUserDefaults.standardUserDefaults().stringForKey("username")
if username != nil {
let myUrl = NSURL(string: "http://www.casacorazon.org/ios.html")
let request = NSMutableURLRequest(URL: myUrl!)
request.HTTPMethod = "POST"
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
if error != nil {
print("Error: \(error)")
}
self.textArray.addObject(responseString as! String)
}
}
task.resume()
} else {
self.textArray.addObject("Error")
self.textArray.addObject("You are not logged in")
}
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 44.0
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Thank you for the help
You have to reload the table view data. Add
self.tableView.reloadData()
right after
self.textArray.addObject(responseString as! String)
I recommend to declare textArray as non-optional Swift Array
var textArray = [String]()
then all occurrences of addObject have to replaced with append
and change the line in cellForRowAtIndexPath to get the value for index path to
cell.textLabel?.text = self.textArray[indexPath.row] // no type casting needed
I have a JSON Data which I want to get into UITable. The data is dynamic so table should update every time view loads. Can anyone help?
{
data = (
{
id = 102076330;
name = "Vicky Arora";
}
)
}
try this....
When you receive response,get the whole array of dictionary
if let arr = response["data"] as? [[String:String]] {
YourArray = arr
// Define YourArray globally
}
Then in tableview cell,cellForRowAtIndexPath method
if let name = YourArray[indexpath.row]["name"] as? String{
label.text = name
}
//Same You can done with id
And don't forget to set number of rows
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return YourArray.count
}
Try this one. But this sample i'm using Alamofire and SwitfyJSON. Import it using CocoaPod.
import UIKit
import Alamofire
class TableViewController: UITableViewController{
var users: [JSON] = []
override func viewDidLoad() {
super.viewDidLoad()
Alamofire.request(.GET, "http://xxxxx/users.json").responseJSON { (request, response, json, error) in
if json != nil {
var jsonObj = JSON(json!)
if let data = jsonObj["data"].arrayValue as [JSON]?{
self.users = data
self.tableView.reloadData()
}
}
}
}
// 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.
return users.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("UserCell", forIndexPath: indexPath) as! UITableViewCell
let user = users[indexPath.row]
if let idLabel = cell.viewWithTag(100) as? UILabel {
if let id = user["id"].string{
idLabel.text = id
}
}
if let nameLabel = cell.viewWithTag(101) as? UILabel {
if let name = user["name"].string{
nameLabel.text = name
}
}
return cell
}
}
If you are up to using Core Data, I would suggest using the NSFetchedRequest.
Every time you are getting the data from the server, save it to Core data, and that will automatically update the table view.
Here is a tutorial from Ray Wenderlich