Error firestore - ios

I just started to learn firestore, i created simple app like a example from googleFirestore (in github).
When i change or create new data in firestore i get an error when my app is start in this line:
fatalError("Error")
I so understand the app is not like creating new data, how can I avoid this error and create data in real time?
My code:
private var hall: [Hall] = []
private var documents: [DocumentSnapshot] = []
fileprivate var query: Query? {
didSet {
if let listener = listener {
listener.remove()
observeQuery()
}
}
}
private var listener: ListenerRegistration?
fileprivate func observeQuery() {
guard let query = query else { return }
stopObserving()
listener = query.addSnapshotListener { [unowned self] (snapshot, error) in
guard let snapshot = snapshot else {
print("Error fetching snapshot results: \(error!)")
return
}
let models = snapshot.documents.map { (document) -> Hall in
if let model = Hall(dictionary: document.data()) {
return model
} else {
fatalError("Error")
}
}
self.hall = models
self.documents = snapshot.documents
self.tableView.reloadData()
}
}
func stopObserving() {
listener?.remove()
}
func baseQuery() -> Query {
return Firestore.firestore().collection("searchStudios").limit(to: 50)
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.tableFooterView = UIView()
query = baseQuery()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
self.setNeedsStatusBarAppearanceUpdate()
observeQuery()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(true)
stopObserving()
}
override var preferredStatusBarStyle: UIStatusBarStyle {
set {}
get {
return .lightContent
}
}
deinit {
listener?.remove()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ResultTableViewCell
cell.populate(hall: hall[indexPath.row])
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return hall.count
}
I can delete data, but not can add new data.
UPDATE:
struct Hall:
import Foundation
protocol DocumentSerializable {
init?(dictionary: [String: Any])
}
struct Hall {
var description: String
var image: String
var meters: Double
var name: String
var price: Int
var studioHallAddress: String
var studioHallName: String
var studioHallLogo: String
var dictionary: [String: Any] {
return [
"description": description,
"image": image,
"meters": meters,
"name": name,
"price": price,
"studioHallAddrees": studioHallAddress,
"studioHallName": studioHallName,
"studioHallLogo": studioHallLogo
]
}
}
extension Hall: DocumentSerializable {
init?(dictionary: [String : Any]) {
guard let description = dictionary["description"] as? String,
let image = dictionary["image"] as? String,
let meters = dictionary["meters"] as? Double,
let name = dictionary["name"] as? String,
let price = dictionary["price"] as? Int,
let studioHallAddress = dictionary["studioHallAddress"] as? String,
let studioHallName = dictionary["studioHallName"] as? String,
let studioHallLogo = dictionary["studioHallLogo"] as? String else { return nil }
self.init(description: description,
image: image,
meters: meters,
name: name,
price: price,
studioHallAddress: studioHallAddress,
studioHallName: studioHallName,
studioHallLogo: studioHallLogo)
}
}

Related

Saving document ID so it can be used throughout the ViewController

I am new to Swift development, so sorry if this is a stupid question. I'm having issues with saving the Firestore document ID to the cell of my to do.
My goal:
Save the document ID of the to-do so it can be used in my ChangeButton protocol.
The app is a to-do list-style app. The changeButton refers to changing the button from an empty circle to a filled circle.
My cellForRowAt in my mainViewController:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 && indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "inputCell", for: indexPath) as! InputCell
cell.delegate = self
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "taskCell", for: indexPath) as! TaskCell
let current = sections[indexPath.section].items[indexPath.row]
cell.taskNameLabel.text = current.name
if current.checked {
cell.checkBoxOutlet.setBackgroundImage(#imageLiteral(resourceName: "checkBoxFILLED "), for: UIControl.State.normal)
} else {
cell.checkBoxOutlet.setBackgroundImage(#imageLiteral(resourceName: "checkBoxOUTLINE "), for: UIControl.State.normal)
}
cell.delegate = self
cell.items = sections[indexPath.section].items
cell.indexSection = indexPath.section
cell.indexRow = indexPath.row
cell.itemID = sections[indexPath.section].items[indexPath.row].itemID
// print("cell.itemID is \(cell.itemID)")
// print("sections.itemID is \(sections[indexPath.section].items[indexPath.row].itemID)")
return cell
}
}
My changeButton function in mainViewController
func changeButton(state: Bool, indexSection: Int?, indexRow: Int?, itemID: String?) {
print("The item ID is \(itemID)")
print("The item ID section is \(sections[indexSection!].items[indexRow!].itemID)")
sections[indexSection!].items[indexRow!].checked = state
print("Line 175 ID is \(itemID)")
if let itemID = itemID {
let itemRef = db.collection(K.FStore.lists).document(currentListID!).collection(K.FStore.sections).document("\(indexSection!)").collection(K.FStore.items).document(itemID)
if sections[indexSection!].items[indexRow!].checked {
itemRef.updateData([
K.FStore.isChecked : true,
K.FStore.checkedBy: currentUserID!
]) { err in
if let err = err {
print("Error writing document: \(err)")
} else {
print("Document successfully written!")
}
}
} else {
itemRef.updateData([
K.FStore.isChecked : false
]) { err in
if let err = err {
print("Error writing document: \(err)")
} else {
print("Document successfully written!")
}
}
}
} else {
print("No item ID")
}
tableView.reloadData()
}
My loadItems and loadFunctions in my mainViewController
func loadItems(listID: String, section: Int) {
let itemRef = db.collection(K.FStore.lists).document(listID).collection(K.FStore.sections).document("(section)").collection(K.FStore.items)
var itemArray = Task
itemRef.getDocuments() { (querySnapshot, error) in
if let error = error {
print("Error getting documents: \(error)")
} else {
for document in querySnapshot!.documents {
let name = document.data()["name"] as? String
let isChecked : Bool = (document.data()["isChecked"] != nil)
let newItem = Task(name: name ?? "FIREBASE ERROR", isChecked: isChecked)
itemArray.append(newItem)
// print(newItem.checked)
}
}
// print(itemArray)
self.sections[section].items = itemArray
self.tableView.reloadData()
}
}
//MARK: - Load sections
func loadSections(listID: String) {
let listRef = db.collection(K.FStore.lists).document(listID)
listRef.getDocument { (document, error) in
if let document = document, document.exists {
let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
let sectionNames = document.data()!["sections"] as? [String]
if let sectionNames = sectionNames {
for (index, item) in sectionNames.enumerated() {
let newSection = Section(name: item, isExpanded: true, items: [])
self.sections.append(newSection)
self.loadItems(listID: listID, section: index)
}
}
self.tableView.reloadData()
} else {
print("Document does not exist")
}
}
}
My Task class
class Task {
var name = ""
var checked = false
var date = Date()
var category: String
var number: Int
var itemID: String?
My TaskCell
protocol ChangeButton {
func changeButton(state: Bool, indexSection: Int?, indexRow: Int?, itemID: String?)
}
class TaskCell: UITableViewCell {
#IBAction func checkBoxAction(_ sender: Any) {
// print("The item ID is \(itemID)")
if items![indexRow!].checked {
delegate?.changeButton(state: false, indexSection: indexSection!, indexRow: indexRow!, itemID: itemID)
print("Line 22 \(itemID)")
} else {
delegate?.changeButton(state: true, indexSection: indexSection!, indexRow: indexRow!, itemID: itemID)
print("Line 25 \(itemID)")
}
}
#IBOutlet weak var taskNameLabel: UILabel!
#IBOutlet weak var checkBoxOutlet: UIButton!
var delegate: ChangeButton?
var indexSection: Int?
var indexRow: Int?
var tasks: [[Task]]?
var items: [Task]?
var itemID: String?
}
I am completely lost in how I can fix this. As you can see, I've tried a lot of print statements to figure out where the itemID can be loaded.
This is what I get back from those print statements:
Line 25 nil
The item ID is nil
The item ID section is nil
Line 175 ID is nil
No item ID
Line 22 nil
Please let me know if I forgot to include anything, and sorry for this extremely long post.
Thanks a ton,
Matt
Firstly,
We don't trust cells because it's reusable so we need a static class.
When cell will be reuse you can lost your data
I create some examples. Maybe it'll be helpful
// This is our model
class Task {
var name = ""
var checked = false
var date = Date()
var category: String
var number: Int
var itemID: String?
public init() {
self.category = ""
self.number = 0
}
}
// Extension for init from firebase response
extension Task {
convenience init(with firebase: [String: Any]) {
self.init()
self.name = (firebase["name"] as? String) ?? ""
}
}
// We create service for document
// We use this service like an API
final class DocumentService {
static let shared = DocumentService()
private let database: FirebaseDatabase
private var tasks: [[Task]] = []
public init(database: FirebaseDatabase = FirebaseDatabase()) {
self.database = database
}
func load(in section: Int, completion: #escaping (([Task]) -> Void)) {
database.loadData(section: section) { [unowned self] tasks in
self.tasks[section] = tasks.map(Task.init)
completion(self.tasks[section])
}
}
func check(at indexPath: IndexPath, isChecked: Bool) {
tasks[indexPath.section][indexPath.row].checked = isChecked
}
}
// We create firebase database class we can add some features in here
final class FirebaseDatabase {
func loadData(section: Int, completion: #escaping (([[String: Any]]) -> Void)) {
// TODO: firebase load data
let response: [[String: Any]] = [
["name": "Stackoverflow"]
]
completion(response)
}
}
final class TestController: UIViewController {
private let service = DocumentService.shared
override func viewDidLoad() {
super.viewDidLoad()
service.load(in: 0) { tasks in
// TODO
}
}
}
Thank you for your answer, #Vicaren. Fortunately, the solution was more simple than that. In the end, I found that I forgot to pass in the itemID argument in the loadItems() function. Thank you.

Get parent key in UITableview with firebase

I have my firebase database structured like this:
Snap (-KWLSAIh5WJvNJOkxBEr) {
beschrijving = "description";
image = "link to image";
title = "title";
}
Snap (-KWLSTak0H20X_2Qnanv) {
beschrijving = "description";
image = "link to image";
title = "title";
}
This is the code I am using to display this in a TableView:
import UIKit
import Firebase
class NieuwsTableViewController: UITableViewController {
var users = [UsersII]()
let cellId = "IdCell"
override func viewDidLoad() {
super.viewDidLoad()
fetchUser()
}
func fetchUser() {
Database.database().reference().child("Blog").observe(.childAdded, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let user = UsersII(dictionary: dictionary)
self.users.append(user)
print(snapshot)
DispatchQueue.main.async(execute: {
self.tableView.reloadData()
})
}
}, withCancel: nil)
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return users.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> lllTableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
let user = users.reversed()[indexPath.row]
cell.textLabel?.text = user.name
return cell as! lllTableViewCell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let message = users.reversed()[indexPath.row]
guard let beschrijving = message.beschrijving else {
return
}
guard let image = message.plaatje else {
return
}
guard let titel = message.name else {
return
}
UserDefaults.standard.set(beschrijving, forKey: "nieuwsBeschrijving")
UserDefaults.standard.set(image,forKey: "nieuwsPlaatje")
UserDefaults.standard.set(titel, forKey: "nieuwsTitel")
self.performSegue(withIdentifier: "gotonews", sender: nil)
}
}
And I don't know if you will need this to answer this question but I'll also post the "UsersII" (defined as users just above the viewDidLoad method) in case this is needed to answer the question.
import UIKit
class UsersII: NSObject {
var name: String?
var beschrijving: String?
var plaatje: String?
init(dictionary: [String: Any]) {
self.name = dictionary["title"] as? String ?? ""
self.beschrijving = dictionary["beschrijving"] as? String ?? ""
self.plaatje = dictionary["image"] as? String ?? ""
}
}
so what I want to achieve is that if you click on one of the cells, you get the parent id of the article, so in this case that would be the "-KWLSAIh5WJvNJOkxBEr or -KWLSTak0H20X_2Qnanv" I mentioned above in my firebase database structure.
Here is what i was saying you to do:
Your model class:
class UsersII: NSObject {
var parentId: String?
var name: String?
var beschrijving: String?
var plaatje: String?
init(dictionary: [String: Any],parentId:String) {
self.name = dictionary["title"] as? String ?? ""
self.beschrijving = dictionary["beschrijving"] as? String ?? ""
self.plaatje = dictionary["image"] as? String ?? ""
self.parentId = parentId
}
}
Fetch user method:
func fetchUser() {
Database.database().reference().child("Blog").observe(.childAdded, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let user = UsersII(dictionary: dictionary,parentId:snapshot.key)
self.users.append(user)
print(snapshot)
DispatchQueue.main.async(execute: {
self.tableView.reloadData()
})
}
}, withCancel: nil)
}
And finaly you didSelect:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let message = users.reversed()[indexPath.row]
guard let beschrijving = message.beschrijving else {
return
}
guard let image = message.plaatje else {
return
}
guard let titel = message.name else {
return
}
guard let parentId = message.name else
{
return
}
UserDefaults.standard.set(beschrijving, forKey: "nieuwsBeschrijving")
UserDefaults.standard.set(image,forKey: "nieuwsPlaatje")
UserDefaults.standard.set(titel, forKey: "nieuwsTitel")
UserDefaults.standard.set(parentId,forKey: "nieuwsParentId")
self.performSegue(withIdentifier: "gotonews", sender: nil)
}
}

The app crashes when adding new keys in firestore

I made a test application following the example of Google with github, but with a few changes (less keys used in the firestore and less filters).
The problem is this, the app crashing when I added new keys in the firestore, but the app works with two keys previously added.
Crashes and shows error on fatalError("error"). I can not understand why with two keys the application works, but if i begin to use the third key (hall) then the app crashes.
What could be the problem?
It's my code:
class ViewControllerTwo: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var tableView: UITableView!
private var sweets: [Sweet] = []
private var document: [DocumentSnapshot] = []
fileprivate var query: Query? {
didSet {
if let listener = listener {
listener.remove()
}
}
}
private var listener: FIRListenerRegistration?
fileprivate func observeQuery() {
guard let query = query else { return }
stopObserving()
listener = query.addSnapshotListener { [unowned self] (snapshot, error) in
guard let snapshot = snapshot else {
print("Error fetching snapshot results: \(error!)")
return
}
let models = snapshot.documents.map { (document) -> Sweet in
if let model = Sweet(dictionary: document.data()) {
return model
} else {
fatalError("error")
}
}
self.sweets = models
self.document = snapshot.documents
self.tableView.reloadData()
}
}
#IBAction func filterButton(_ sender: Any) {
present(filters.navigationController, animated: true, completion: nil)
}
lazy private var filters: (navigationController: UINavigationController, filtersController: FilterViewController) = {
return FilterViewController.fromStoryboard(delegate: self)
}()
fileprivate func stopObserving() {
listener?.remove()
}
fileprivate func baseQuery() -> Query {
return Firestore.firestore().collection("sweets").limit(to: 50)
}
override func viewDidLoad() {
super.viewDidLoad()
query = baseQuery()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
observeQuery()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(true)
stopObserving()
}
deinit {
listener?.remove()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sweets.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ViewControllerCell
let sweet = sweets[indexPath.row]
cell.studioNameLabel.text = sweet.name
cell.studioAddressLabel.text = sweet.content
cell.hallNameLabel.text = sweet.hall
return cell
}
}
extension ViewControllerTwo: FiltersViewControllerDelegate {
func query(withCategory title: String?) -> Query {
var filtered = baseQuery()
if let title = title, !title.isEmpty {
filtered = filtered.whereField("title", isEqualTo: title)
}
return filtered
}
func controller(_ controller: FilterViewController, didSelectCategory title: String?) {
let filtered = query(withCategory: title)
self.query = filtered
observeQuery()
}
}
class ViewControllerCell: UITableViewCell {
#IBOutlet weak var studioNameLabel: UILabel!
#IBOutlet weak var studioAddressLabel: UILabel!
#IBOutlet weak var hallNameLabel: UILabel!
}
And my struct:
protocol DocumentSerializable {
init?(dictionary:[String:Any])
}
struct Sweet {
var name:String
var content:String
var hall:String
var dictionary:[String:Any] {
return [
"name": name,
"content" : content,
"hall" : hall
]
}
}
extension Sweet : DocumentSerializable {
static let title = [
"one",
"two",
"three",
"four"
]
init?(dictionary: [String : Any]) {
guard let name = dictionary["name"] as? String,
let content = dictionary["content"] as? String,
let hall = dictionary["hall"] as? String else { return nil }
self.init(name: name, content: content, hall: hall)
}
}
My project in google drive
google drive
google service info.plist
You just need to reinstall app once you add any new key to you existing structure.
So you should decide before structure implementation that what keys you will need. Or you can reinstall app if you add new key in future.

How do I create a drill down UITable in a single view using pre-populated data from API call?

I am trying to create a selection method for users to pick a football team using UITableView.
When the View Controller loads I make an API call and fetch and populated the following arrays in custom structs:
Country [name,id]
Divisions [id, country_id, name]
Teams [id, division_id, name]
The process is:
The user first selects a country > the ID of this country is then used to populate the table with all the divisions from that country > a division is selected which brings up all the teams in that division > a team is selected and the team name and id are passed to a variable to be used elsewhere.
At the moment the table displays all the countries. Once a user selects a country I am using print (self.newCountries[cellCountryId!]) to identifies and print the name of the country and it's id.
How do I now take that data and re-populate the table where Divisions.country_id = (self.newCountries[cellCountryId!])
This is my code:
import UIKit
class PickTeamViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var teamsTableView: UITableView!
var pickedCountryID: Int?
var selectedCellCountryTitle: String?
var cellCountryId: Int?
struct Country {
var name: String?
var countryId: String?
init(_ dictionary: [String : String]) {
self.name = dictionary["name"]
self.countryId = dictionary["id"]
}
}
struct Divisions {
var divisionName: String?
var divisionId: String?
init(_ dictionary: [String : String]) {
self.divisionName = dictionary["name"]
self.divisionId = dictionary["country_id"]
}
}
struct Teams {
var teamName: String?
var newTeamId: String?
init(_ dictionary: [String : String]) {
self.teamName = dictionary["name"]
}
}
struct TeamId {
var newTeamId: String?
init(_ dictionary: [String : String]) {
self.newTeamId = dictionary["id"]
}
}
var newCountries = [Country]()
var newDivisions = [Divisions]()
var newTeams = [Teams]()
var newTeamId = [TeamId]()
override func viewDidAppear(_ animated: Bool) {
let myUrl = URL(string: "http://www.quasisquest.uk/KeepScore/getTeams.php?");
var request = URLRequest(url:myUrl!);
request.httpMethod = "GET";
let task = URLSession.shared.dataTask(with: myUrl!) { (data: Data?, response: URLResponse?, error: Error?) in
DispatchQueue.main.async
{
if error != nil {
print("error=\(error)")
return
}
do{
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:Any]
print (json)
if let arr = json?["countries"] as? [[String:String]] {
self.newCountries = arr.flatMap { Country($0) }
self.teamsTableView.reloadData()
}
if let arr = json?["divisions"] as? [[String:String]] {
self.newDivisions = arr.flatMap { Divisions($0) }
}
if let arr = json?["teams"] as? [[String:String]] {
self.newTeams = arr.flatMap { Teams($0) }
}
self.teamsTableView.reloadData()
} catch{
print(error)
}
}
}
task.resume()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.newCountries.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let country = newCountries[indexPath.row]
let cell = UITableViewCell()
cell.textLabel?.text = country.name
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
cellCountryId = indexPath.row
print (self.newCountries[cellCountryId!])
}
override func viewDidLoad() {
super.viewDidLoad()
self.teamsTableView.delegate = self
self.teamsTableView.dataSource = self
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func backButtonTapped(_ sender: AnyObject) {
self.dismiss(animated: true) {
return
}
}
}

How do I extract a variable from a UITable DidSelectAtRow?

I have an instance where a user picks from a UITable. The selected record has a name and an id associated with it.
At the moment to verify the name and id are being correctly reported I am using
let tempCountryId = (self.newCountries[cellCountryId!])
print (tempCountryId)
Country(name: Optional("England"), countryId: Optional("5"))
I want to be able to store that countryId in a variable so I can repopulate my UITable with data (Football Divisions) that match the countryId '5'
How do I do this?
This is my full script:
import UIKit
class PickTeamViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var teamsTableView: UITableView!
var pickedCountryID: Int?
var selectedCellCountryTitle: String?
var cellCountryId: Int?
struct Country {
var name: String?
var countryId: String?
init(_ dictionary: [String : String]) {
self.name = dictionary["name"]
self.countryId = dictionary["id"]
}
}
struct Divisions {
var divisionName: String?
var divisionId: String?
init(_ dictionary: [String : String]) {
self.divisionName = dictionary["name"]
self.divisionId = dictionary["country_id"]
}
}
struct Teams {
var teamName: String?
var newTeamId: String?
init(_ dictionary: [String : String]) {
self.teamName = dictionary["name"]
}
}
struct TeamId {
var newTeamId: String?
init(_ dictionary: [String : String]) {
self.newTeamId = dictionary["id"]
}
}
var newCountries = [Country]()
var newDivisions = [Divisions]()
var newTeams = [Teams]()
var newTeamId = [TeamId]()
override func viewDidAppear(_ animated: Bool) {
let myUrl = URL(string: "http://www.quasisquest.uk/KeepScore/getTeams.php?");
var request = URLRequest(url:myUrl!);
request.httpMethod = "GET";
let task = URLSession.shared.dataTask(with: myUrl!) { (data: Data?, response: URLResponse?, error: Error?) in
DispatchQueue.main.async
{
if error != nil {
print("error=\(error)")
return
}
do{
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:Any]
print (json)
if let arr = json?["countries"] as? [[String:String]] {
self.newCountries = arr.flatMap { Country($0) }
self.teamsTableView.reloadData()
}
if let arr = json?["divisions"] as? [[String:String]] {
self.newDivisions = arr.flatMap { Divisions($0) }
}
if let arr = json?["teams"] as? [[String:String]] {
self.newTeams = arr.flatMap { Teams($0) }
}
self.teamsTableView.reloadData()
} catch{
print(error)
}
}
}
task.resume()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.newCountries.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let country = newCountries[indexPath.row]
let cell = UITableViewCell()
cell.textLabel?.text = country.name
cell.textLabel?.font = UIFont(name: "Avenir", size: 12)
cell.textLabel?.textColor = UIColor.black
cell.backgroundColor = UIColor.white
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
cellCountryId = indexPath.row
// print (self.newCountries[cellCountryId!])
let tempCountryId = (self.newCountries[cellCountryId!])
print (tempCountryId)
}
override func viewDidLoad() {
super.viewDidLoad()
self.teamsTableView.delegate = self
self.teamsTableView.dataSource = self
// Do any additional setup after loading the view.
}
}
As discussed in the comments you should use another view controller to show the details. In didSelectRowAtIndexPath method take out the selected country from newCountries array and pass it to the DetailViewController.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let countryDetailsVC = self.storyboard?.instantiateViewController(withIdentifier: "CountryDetailsViewController") as! DetailViewController
countryDetailsVC.country = selectedCountry
present(countryDetailsVC, animated: true, completion: nil)
}
Now that you have the country Struct you can show its details in the DetailViewController.
Your table is populated from the array newCountries. So, to replace the contents of the table, you would need to replace the contents of newCountries and reload the table.
But that is not a very wise strategy. It would be better to show a different view controller with a different table and a different data array.

Resources