would you please help me to solve this error .I'am trying to download an Image From Firebase Database, this is my code and I put a snapshot for the error . ThanksThis is a snapshot for the error in Xcode
import UIKit
import FirebaseDatabase
class ViewController: UIViewController , UITableViewDataSource , UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var ref:FIRDatabaseReference?
var Handle:FIRDatabaseHandle?
var myClass = [Post]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
ref=FIRDatabase.database().reference()
Handle = ref?.child("Posts").observe(.childAdded, with: { (snapshot) in
let post = snapshot.valueInExportFormat()
for url in post! as! [Post] { // Error Here
self.myClass.append(url)
self.tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return myClass.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)as? TableViewCell{
cell.MyImage.alpha = 0
cell.textLabel?.text = PostData[indexPath.row]
DispatchQueue.main.async(execute: {
let imgurl = URL(string : self.myClass [(indexPath as NSIndexPath).row].url)
let imgdata = NSData(contentsOf: imgurl!)
cell.MyImage.image = UIImage(data: imgdata as! Data)
UIView.animate(withDuration: 0.5, animations: {
cell.MyImage.alpha = 1
})
})
return cell
} else {
let cell = TableViewCell()
DispatchQueue.main.async(execute: {
let imgurl = URL(string : self.myClass [(indexPath as NSIndexPath).row].url)
let imgdata = NSData(contentsOf: imgurl!)
cell.MyImage.image = UIImage(data: imgdata as! Data)
})
return cell
}
}
}
})
}
Sometimes simple is the way to go.
assume you have a Firebase structure
Planets
planet_4
some_text = "My post about Mars"
image_url = "images/mars.jpg"
planet_2
some_text = "My post about Venus"
image_url = "images/venus.jpg"
and suppose we want to load each text and image and display in a tableview. We can do it one of two ways, one at a time with .childAdded or all at once with .value. In this example, we'll walk through them one at a time.
let planetsRef = myRootRef.child("Planets")
planetsRef.observe(.childAdded, with: { snapshot in
let dict = snapshot.value as! [String: AnyObject]
let text = dict["text"]
let imageUrl = dict["image_url"]
// Create a reference to the file you want to download
let planetRef = storageRef.child(imageUrl) //storageRef is defined elsewhere
// Download in memory with a maximum allowed size
// of 1MB (1 * 1024 * 1024 bytes)
planetRef.dataWithMaxSize(1 * 1024 * 1024) { (data, error) -> Void in
if (error != nil) {
// Got an error so handle it
} else {
// Data for "images/some planet.jpg" is returned
// let planetImage: UIImage! = UIImage(data: data!)
// then add the text and the image to your dataSource array
// and reload your tableview.
}
})
})
This is not tested but will provide the general idea
Maybe you want:
for url in post! {
var wrappedPost = Post()
wrappedPost.url = url
... use wrappedPost for whatever you need a Post object for
}
Related
I retrieve data from MySql via PHP file to get users information and scores to load them in a table. I need to get the value of the first 3 users and put them in a Label outside the Table, it is like game leaders list. I attached an image to explain the idea.
Here is the structure code:
import Foundation
protocol HomeModelProtocol: AnyObject {
func itemsDownloaded(items: NSArray)
}
class HomeModel: NSObject, URLSessionDataDelegate {
weak var delegate: HomeModelProtocol!
let urlPath = "https://mywebsite.com/folder/callUserList.php" //this will be changed to the path where service.php lives
func downloadItems() {
let url: URL = URL(string: urlPath)!
let defaultSession = Foundation.URLSession(configuration: URLSessionConfiguration.default)
let task = defaultSession.dataTask(with: url) { (data, response, error) in
if error != nil {
print("Failed to download data")
}else {
print("Data downloaded")
self.parseJSON(data!)
}
}
task.resume()
}
func parseJSON(_ data:Data) {
var jsonResult = NSArray()
do{
jsonResult = try JSONSerialization.jsonObject(with: data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
} catch let error as NSError {
print(error)
}
var jsonElement = NSDictionary()
let users = NSMutableArray()
for i in 0 ..< jsonResult.count
{
jsonElement = jsonResult[i] as! NSDictionary
let user = UsersModel()
//the following insures none of the JsonElement values are nil through optional binding
if let name = jsonElement["name"] as? String,
let email = jsonElement["email"] as? String,
let phoneNumber = jsonElement["phone"] as? String,
let userImage = jsonElement["image"] as? String
{
user.name = name
user.email = email
user.phoneNumber = phoneNumber
user.userImage = userImage
}
users.add(user)
}
DispatchQueue.main.async(execute: { () -> Void in
self.delegate.itemsDownloaded(items: users)
})
}
}
Here is the model:
import Foundation
class UsersModel: NSObject {
//properties
var name: String?
var email: String?
var phoneNumber: String?
var userImage: String?
//empty constructor
override init()
{
}
//construct with #name, #address, #latitude, and #longitude parameters
init(name: String, email: String, phoneNumber: String, userImage: String) {
self.name = name
self.email = email
self.phoneNumber = phoneNumber
self.userImage = userImage
}
//prints object's current state
override var description: String {
return "Name: \(String(describing: name)), Email: \(String(describing: email)), Phone Number: \(String(describing: phoneNumber)), User Image: \(String(describing: userImage))"
}
}
Here is the code in the TableView controller:
var feedItems: NSArray = NSArray()
override func viewDidLoad() {
super.viewDidLoad()
let homeModel = HomeModel()
homeModel.delegate = self
homeModel.downloadItems()
}
func itemsDownloaded(items: NSArray) {
feedItems = items
self.listTableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of feed items
return feedItems.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Retrieve cell
let cellIdentifier: String = "BasicCell"
let myCell: WinnerTableCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) as! WinnerTableCell
// Get the location to be shown
let item: UsersModel = feedItems[indexPath.row] as! UsersModel
// Get references to labels of cell
myCell.lbTextName!.text = item.name
return myCell
}
The data shows in the Table but I have no idea how to fill the 3 label with the 3 first users from the Table.
How can I get these values from the table and pass it to a label in the same ViewController?
Thanks
When adding this code:
if feedItems.count >= 3 {
lblFirstWinner.text = feedItems[0].name // 1st winner
lblSecondWinner.text = feedItems[1].name // 2nd winner
lblThirdWinner.text = feedItems[2].name // 3rd winner
}
it shows error: Value of type 'Any' has no member 'name'
Change itemsDownloaded method as
func itemsDownloaded(items: NSArray) {
feedItems = items
self.listTableView.reloadData()
for (index, user) in items.enumerated() {
let user = user as! UserModel
switch index {
case 0: // 1st winner
lblFirstWinner.text = user.name
case 1: // 2nd winner
lblSecondWinner.text = user.name
case 2: // 3rd winner
lblThirdWinner.text = user.name
}
}
}
OR
Change your HomeModelProtocol method and feedItems type to [UsersModel]
protocol HomeModelProtocol: AnyObject {
func itemsDownloaded(items: [UsersModel]) // Changed
}
var feedItems =[UsersModel]() // Changed
override func viewDidLoad() {
super.viewDidLoad()
let homeModel = HomeModel()
homeModel.delegate = self
homeModel.downloadItems()
}
func itemsDownloaded(items: [UsersModel]) {
feedItems = items
self.listTableView.reloadData()
if feedItems.count >= 3 {
lblFirstWinner.text = feedItems[0].name // 1st winner
lblSecondWinner.text = feedItems[1].name // 2nd winner
lblThirdWinner.text = feedItems[2].name // 3rd winner
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of feed items
return feedItems.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Retrieve cell
let cellIdentifier: String = "BasicCell"
let myCell: WinnerTableCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) as! WinnerTableCell
// Get references to labels of cell
myCell.lbTextName!.text = feedItems[indexPath.row].name // Changed
return myCell
}
Just you need to add a few lines in the below function and your solution will be done.
func itemsDownloaded(items: NSArray) {
feedItems = items
self.listTableView.reloadData()
if feedItems.count >= 3 {
lblFirstWinner.text = feedItems[0].name // 1st winner
lblSecondWinner.text = feedItems[1].name // 2nd winner
lblThirdWinner.text = feedItems[2].name // 3rd winner
}
}
Let me know... is it working for you? and please also refer to #vadian comment on your question.
I'm trying to get cell of tableView using UserDefaults, but after i reload app it is always empty
This is my Model:
struct Note: Codable {
var title: String
var description: String
}
class Notes {
var stock: [Note] = []
}
View contoller
var model = Notes()
This is how i get data
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.register(UINib(nibName: "TableViewCell", bundle: nil), forCellReuseIdentifier: "TableViewCell")
tableView.reloadData()
if let fetchedData = UserDefaults.standard.data(forKey: "notes") {
let fetchedBookies = try! PropertyListDecoder().decode([Note].self, from: fetchedData)
print(fetchedBookies)
} else {
model.stock = []
}
}
This is my cell
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell") as! TableViewCell
cell.titleOutlet.text = self.model.stock[indexPath.row].title
cell.descriptionOutlet?.text = self.model.stock[indexPath.row].description
return cell
}
How i save data
#IBAction func check(_ sender: Any) {
let newstock = Note(title: "check", description: "check2")
model.stock.append(newstock)
print(model.stock.count)
let bookiesData = try! PropertyListEncoder().encode(model.stock)
UserDefaults.standard.set(bookiesData, forKey: "notes")
tableView.reloadData()
}
Thank you very much!
I recommend you to use Json Encoder/Deocder.
First set your Notes class to conform to Codable:
class Notes: Codable {
var stock: [Note] = []
}
Here is an example of how to use Json Encoder / Decoder:
func save(notes: Notes) throws {
let encoder = JSONEncoder()
do {
let data = try encoder.encode(notes)
UserDefaults.standard.set(data, forKey: "notes")
} catch let error {
throw error
}
}
func load() -> Notes {
guard let data = UserDefaults.standard.data(forKey: "notes") else {
return Notes() // Default
}
let decoder = JSONDecoder()
do {
let object = try decoder.decode(Notes.self, from: data)
return object
} catch {
return Notes() // Default
}
}
In your code just call load() to get your notes from User Defaults
And save(notes:) to save them into User Defaults.
I am trying to get the data I have saved and then load it into the TableView. Currently, if I am saving the object for the first time, the data gets encoded, saved, decoded, read and displayed correctly. However, if the key already exists and I am adding to the existing data, nothing gets displayed in the TableView.
This is currently how I am saving it in the first view controller:
let userEntry = UserEntries(date: String(todayDate), questions: [UserEntries.Question(question: q1Text, answer: q1Answer), UserEntries.Question(question: q2Text, answer: q2Answer)])
var allEntries : [UserEntries] = []
if doesKeyExist(key: "allEntries") == true {
let jsonDecoder = JSONDecoder()
if let data = UserDefaults.standard.data(forKey: "allEntries"),
let userEntries = try? jsonDecoder.decode(UserEntries.self, from: data) {
allEntries = [userEntries]
}
allEntries.insert(userEntry, at: 0)
let jsonEncoder = JSONEncoder()
if let value = try? jsonEncoder.encode(allEntries) {
UserDefaults.standard.set(value, forKey: "allEntries")
UserDefaults.standard.synchronize()
}
} else {
let jsonEncoder = JSONEncoder()
if let value = try? jsonEncoder.encode(userEntry) {
UserDefaults.standard.set(value, forKey: "allEntries")
UserDefaults.standard.synchronize()
}
}
let newViewController = storyboard?.instantiateViewController(withIdentifier: "tabViewController") as! UITabBarController
present(newViewController, animated: true, completion: nil)
}
This is how I'm displaying it in the TableView
var TableData : [UserEntries] = []
override func viewDidLoad() {
super.viewDidLoad()
let jsonDecoder = JSONDecoder()
if let data = UserDefaults.standard.data(forKey: "allEntries"),
let userEntries = try? jsonDecoder.decode(UserEntries.self, from: data) {
print(userEntries.date)
TableData = [userEntries]
}
// 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 numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return TableData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "entryCell", for: indexPath)
cell.textLabel?.text = TableData[indexPath.row].date
cell.detailTextLabel?.text = TableData[indexPath.row].questions[0].answer
return cell
}
I have a feeling that this is a logic error, in getting/displaying the data in the TableView, but am unsure of what exactly it is/how to fix it. Thank you for your help!
I don't know what your doesKeyExists function does but you can improve your data manipulation by this way:
let userEntry = UserEntries(date: String(todayDate), questions: [UserEntries.Question(question: q1Text, answer: q1Answer), UserEntries.Question(question: q2Text, answer: q2Answer)])
var allEntries : [UserEntries] = []
let jsonDecoder = JSONDecoder()
if let data = UserDefaults.standard.data(forKey: "allEntries"),
let userEntries = try? jsonDecoder.decode([UserEntries].self, from: data) {
allEntries = userEntries
}
allEntries.insert(userEntry, at: 0)
let jsonEncoder = JSONEncoder()
if let value = try? jsonEncoder.encode(allEntries) {
UserDefaults.standard.set(value, forKey: "allEntries")
UserDefaults.standard.synchronize()
}
let newViewController = storyboard?.instantiateViewController(withIdentifier: "tabViewController") as! UITabBarController
present(newViewController, animated: true, completion: nil)
}
And the problem with your controller is that you are saving only one entry to UserDefaults. Try to change your code to
let jsonDecoder = JSONDecoder()
if let data = UserDefaults.standard.data(forKey: "allEntries"),
let userEntries = try? jsonDecoder.decode([UserEntries].self, from: data) {
print(userEntries)
TableData = userEntries
}
Sorry if this is asked already but I haven't found a solution for it. I'm new to Swift so please bear with me. I can't figure out why I keep getting an error of Thread 1: Fatal Error: Index out of range. I've used the same method before in displaying a txt file to which I never got a problem with before so this is the first time. I'm trying to display coordinates as the text details with the date and time as text in the cells itself.
Date and Time
Latitude, Longitude
Something like the above (Imagine it in a cell)
The following is my code for the program
import UIKit
import MapKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
//Array to store the list
var storeCoordinates = [String: String]()
var arrayClient = NSMutableArray()
var readings: [String] = [" "]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//Get path of where the file is
let path = Bundle.main.path(forResource: "gps_coords", ofType: "csv")
//Use filemanager to check if the file exist to avoid crashing if it doesn't exist
let fileMgr = FileManager.default
//Display the number of line counts we have
if fileMgr.fileExists(atPath: path!){
do {
let fulltext = try String(contentsOfFile: path!, encoding: String.Encoding.utf8)
readings = fulltext.components(separatedBy: "\n") as [String]
for i in 0..<readings.count{
let listData = readings[i].components(separatedBy: ";") as [String]
storeCoordinates["Latitude"] = "\(listData[0])"
storeCoordinates["Longitude"] = "\(listData[1])"
storeCoordinates["DateAndTime"] = "\(listData[2])"
arrayClient.add(storeCoordinates)
}
} catch let error as NSError {
print("Error: \(error)")
}
}
self.title = "Number of entries: \(arrayClient.count)"
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayClient.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellReuseIdentifier", for: indexPath)
let client = arrayClient[indexPath.row] as AnyObject
cell.textLabel?.text = "\(client.object(forKey: "DateAndTime")!)"
cell.detailTextLabel?.text = "\(client.object(forKey: "Latitude")!) \(client.object(forKey: "Longitude")!)"
return cell
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
}
The error I had is on storeCoordinates["Latitude"] = "\(listData[0])"
Using breakpoints, it shows the Latitude value is not empty along with Longitude and DateAndTime but if I try to run the app in the simulator, it gives the error Thread 1: Fatal Error: Index out of range. So far no luck in trying to figure out how to fix this. If you could help me figure it out, it would mean a lot to me. Please and thank you.
I regard the unreliable CSV format as the origin of the issue.
This is a quick tutorial to use a better format (JSON) and a more robust data source.
Part 1: Convert CSV to JSON
Create a new Blank Playground (press ⌥⇧⌘N) platform macOS
Press ⌘0 to show the project navigator of the Playground.
⌥-drag the CSV file from the project navigator of the main project into the Resources folder of the Playground.
Paste the following code into the Playground, it's based on your code to parse the CSV. It converts the CSV to JSON and creates a file gps_coords.json on the desktop. You'll get a fatal error if any field is missing.
struct Coordinate : Encodable {
let latitude, longitude, dateAndTime : String
}
let url = Bundle.main.url(forResource: "gps_coords", withExtension: "csv")!
let fulltext = try! String(contentsOf: url, encoding: .utf8)
let lines = fulltext.components(separatedBy: .newlines)
let coordinates = lines.map { paragraph -> Coordinate in
let components = paragraph.components(separatedBy: ";")
if components.count != 3 { fatalError("Each line must contain all three fields")}
return Coordinate(latitude: components[0], longitude: components[1], dateAndTime: components[2])
}
do {
let data = try JSONEncoder().encode(coordinates)
let homeURL = URL(fileURLWithPath: NSHomeDirectory())
let destinationURL = homeURL.appendingPathComponent("Desktop/gps_coords.json")
try data.write(to: destinationURL)
} catch { print(error) }
Part 2: Implement the new file
Close the Playground. It's not needed anymore.
Drag the new file from the desktop into the project navigator (make sure Copy If Needed is checked).
Change the ViewController class to
import UIKit
import MapKit
struct Coordinate : Decodable {
let latitude, longitude, dateAndTime : String
}
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var arrayClient = [Coordinate]()
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle.main.url(forResource: "gps_coords", withExtension: "json")!
let data = try! Data(contentsOf: url)
arrayClient = try! JSONDecoder().decode([Coordinate].self, from: data)
self.title = "Number of entries: \(arrayClient.count)"
tableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayClient.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellReuseIdentifier", for: indexPath)
let client = arrayClient[indexPath.row]
cell.textLabel?.text = client.dateAndTime
cell.detailTextLabel?.text = client.latitude + " " + client.longitude
return cell
}
}
Note: The UITableView outlet is missing and I added the line to reload the data. Make also sure that delegate and datasource is connected in Interface Builder from the table view to the ViewController.
Delete the CSV file.
The new code uses a struct Coordinate as data source and decodes the JSON very conveniently with JSONDecoder. Please note the missing type casts and the cumbersome key subscription to get the values from the dictionary.
As in the comment, mentioned by #vadian, It is not possible that you didn't get 0th index. But you add some checks.
Update your code as following:
Some updates are -
Use swift based array [[String: String]] rather NSMutableArray
Initialize the storeCoordinates for each loop cycle and check if your listData have more than 3 items or not
class AViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
//Array to store the list
var arrayClient = [[String: String]]()
var readings: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
//Get path of where the file is
let path = Bundle.main.path(forResource: "gps_coords", ofType: "csv")
//Use filemanager to check if the file exist to avoid crashing if it doesn't exist
let fileMgr = FileManager.default
//Display the number of line counts we have
if fileMgr.fileExists(atPath: path!){
do {
let fulltext = try String(contentsOfFile: path!, encoding: String.Encoding.utf8)
readings = fulltext.components(separatedBy: "\n") as [String]
for i in 0..<readings.count {
// Check if you can get data from `readings[i]`
let listData = readings[i].components(separatedBy: ";") as [String]
if listData.count == 3 {
var storeCoordinates = [String: String]()
storeCoordinates["Latitude"] = "\(listData[0])"
storeCoordinates["Longitude"] = "\(listData[1])"
storeCoordinates["DateAndTime"] = "\(listData[2])"
arrayClient.append(storeCoordinates)
}
}
} catch let error as NSError {
print("Error: \(error)")
}
}
self.title = "Number of entries: \(arrayClient.count)"
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayClient.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellReuseIdentifier", for: indexPath)
let client = arrayClient[indexPath.row]
if let dateTime = client["DateAndTime"], let latitude = client["DateAndTime"], let longitude = client["DateAndTime"] {
cell.textLabel?.text = "\(dateTime)"
cell.detailTextLabel?.text = "\(latitude) \(longitude)"
}
return cell
}
}
I'm clueless as to what is wrong. My console doesn't give me any errors, my code seems fine but nothing is showing up. Could someone check my code, see why it doesn't want to work? My tableView is connected with its delegates and source. Not sure what is the problem.
Here is my code:
private let cellIdentifier = "cell"
private let apiURL = "api link"
class TableView: UITableViewController {
//TableView Outlet
#IBOutlet weak var LegTableView: UITableView!
//API Array
var legislatorArray = [congressClass]()
func getLegislators (fromSession session: NSURLSession) {
//Calling url
if let jsonData = NSURL(string: apiURL) {
// Requesting url
let task = session.dataTaskWithURL(jsonData) {(data, response, error) -> Void in
//Check for errors
if let error = error {print(error)
} else {
if let http = response as? NSHTTPURLResponse {
if http.statusCode == 200 {
//Getting data
if let data = data {
do {
let legislatorData = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers)
//Get API data
if let getData = legislatorData as? [NSObject:AnyObject],
findObject = getData["results"] as? [AnyObject]{
//Return data
for cellFound in findObject{
if let nextCell = cellFound["results"] as? [NSObject:AnyObject],
name = nextCell["first_name"] as? String,
lastName = nextCell["last_name"] as? String,
title = nextCell["title"] as? String,
partyRep = nextCell["party"] as? String,
position = nextCell ["position"] as? String,
id = nextCell ["bioguide_id"] as? String
{
//Add data to array
let addData = congressClass(name: name, lastName: lastName, title: title, party: partyRep, position: position, bioID: id)
self.legislatorArray.append(addData)
}
}//end cellFound
//Adding data to table
dispatch_async(dispatch_get_main_queue()) { () -> Void in
self.tableView.reloadData()
}
}
}
//end do
catch {print(error)}
}//end data
}//end statusCode
}//end http
}//else
}//end task
//Run code
task.resume()
}//end jsonData
}
override func viewDidLoad() {
super.viewDidLoad()
let sessionConfig = NSURLSessionConfiguration.defaultSessionConfiguration()
let urlSession = NSURLSession(configuration: sessionConfig)
getLegislators(fromSession: urlSession)
}
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 Incomplete implementation, return the number of sections
return 1
}
//TableView Rows
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return legislatorArray.count
//return 5
}
//Cell Configuration
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! CellTableView
cell.lesName?.text = legislatorArray[indexPath.row].name + " " + legislatorArray[indexPath.row].lastName
cell.lesTitle?.text = legislatorArray[indexPath.row].title
cell.lesParty?.text = legislatorArray[indexPath.row].party
//These tests worked fine.. the tableView is working. But the data doesn't seem to pass.
//cell.lesName.text = "Name" + " " + "lastName"
//cell.lesTitle.text = "Title goes here"
//cell.lesParty.text = "D"
return cell
}
}
You're not reloading the tableView
The problem is in this piece of code
//-----------------------------
//New empty array for api data
var indexPath:[NSIndexPath] = []
//Adding data to new array
for i in 0..<self.legislatorArray.count{
let secondIndexPath = NSIndexPath(forRow: i, inSection: 0)
indexPath.append(secondIndexPath)
}
//Adding data to table
dispatch_async(dispatch_get_main_queue()) { () -> Void in
self.tableView.insertRowsAtIndexPaths(indexPath, withRowAnimation: .Left)
}
You don't need any of that. You can just reload the tableView as follows:
//Adding data to table
dispatch_async(dispatch_get_main_queue()) { () -> Void in
//You only need to reload it and that should do the trick
self.tableView.reloadData()
}
I know you said your tableView is connected to the delegate and dataSource but it's not showing in your code.
You conformed the ViewController to the correct protocols but you need something like this in your viewDidLoad.
self.tableView.deletage = self
self.tableView.dataSource = self
//I don't know if this was a typo but in your cellForRowAtIndexPath you are using CellTableView
let nibName = UINib(nibName: "CellTableView", bundle:nil)
self.tableView.registerNib(nibName, forCellReuseIdentifier: cellIdentifier)
I created an example of a better design for your implementation
This is for the WebService and your Custom Class
https://github.com/phantomon/Stackoverflow/blob/master/SO1/MyTableView/MyTableView/Models/WebServiceManager.swift
This is for the ViewController with your tableView
https://github.com/phantomon/Stackoverflow/blob/master/SO1/MyTableView/MyTableView/ViewController.swift
You just need to modify the UITableViewCell with your custom one.
And of course review your custom class data.