I managed to include this API from America FAA website in order to download the NOTAM for a pilot. I manage to send the request of the param "api key, location, state". I get back my JSON data and it works fine. Now my problem is I want to display on a tableView one item of the array that I got back in JSON format, is the item called 'all'.
I created the IBOutlet. I gave the cell identifier, but I'm stuck here
import UIKit
import Alamofire
import SwiftyJSON
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
//Constants
let notamUrl = "https://v4p4sz5ijk.execute-api.us-east-1.amazonaws.com/anbdata/states/notams/notams-realtime-list"
let api_key = "mykey"
let notamModel = ModelloNotam()
#IBOutlet weak var tableView: UITableView!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return //????????? i dont know
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath)
// ????????? i dont know
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate=self
tableView.dataSource=self
func getNOTAM (url:String,parameters:[String:String]){
Alamofire.request(url, method: .get, parameters: parameters).responseJSON {
response in
if response.result.isSuccess{
let notamJSON : JSON = JSON (response.result.value!)
self.displayNotam(json: notamJSON)
} else{
print("errore connessione\(response.result.error)")
}
}
}
var locations = "VMMC"
var state = "CHN"
let params : [String : String] = ["locations" : locations, "state" : state, "api_key" : api_key]
getNOTAM(url: notamUrl, parameters: params)
}
func displayNotam (json:JSON) {
let conta = json.count
for var i in 0...conta {
i = i + 1
notamModel.all = json [i]["all"].stringValue
notamModel.type = json [i]["type"].stringValue
// print("The NOTAM type is \(notamModel.type)")
// print(notamModel.all)
// print("************************")
}
}
}
please refer this tutorial https://www.youtube.com/watch?v=sd7d4eoM54U&t=1857s and model data according to JSON file. networking request goes out of main execution queue.
i solve with this code.!!
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellid", for: indexPath)
// let text = array[indexPath.row]
// cell.textLabel?.text=text
(cell.contentView.viewWithTag(1) as! UILabel).text = array[indexPath.row]
(cell.contentView.viewWithTag(2) as! UILabel).text = array2[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
thanks for the help.
Related
I recieves json data from api and totally confused what should I do next to pass this data to custom cell with imageView and labels in order to update UI in tableView.
Getting JSON
import Foundation
struct Breed: Codable {
let name: String?
let origin: String?
let life_span:String?
let temperament: String?
let description: String?
let wikipedia_url: String?
let image: Image?
}
struct Image: Codable {
let url: String?
}
func getDataFromCatsApi() {
let url = URL(string: "https://api.thecatapi.com/v1/breeds")
let task = URLSession.shared.dataTask(with: url!) { data, _ , error in
let decoder = JSONDecoder()
if let data = data {
let breed = try? decoder.decode([Breed].self, from: data)
print (breed as Any)
} else {
print (error as Any)
}
}
task.resume()
}
All data is printed correctly.
In ViewController I have a tableView with custom cell.
import UIKit
class MainVC: UIViewController {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
title = "Cats"
view.backgroundColor = .systemBackground
getDataFromCatsApi()
}
}
extension MainVC: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell",
for: indexPath) as? CustomTableViewCell
return cell ?? CustomTableViewCell()
}
}
Class for custom cell. Here I have imageView and labels for displaying data from json.
import UIKit
class CustomTableViewCell: UITableViewCell {
#IBOutlet weak var catImageView: UIImageView!
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var originLabel: UILabel!
#IBOutlet weak var addToFavButton: UIButton!
}
First of all, you are not returning anything from getDataFromCatsApi(). Since it is an asynchronous call, you have to implement a way to get the values either by using a callback or a delegate. In this case callback would suffice.
Then once you receive a value from the api call, set those values in func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) in which you can use cell.nameLabel.text = <received value> and etc.
First of all declare only those properties as optional which can be nil
struct Breed: Decodable {
let name, origin, lifeSpan, temperament, description: String
let wikipediaUrl: String?
let image: Image?
}
struct Image: Decodable {
let url: String?
}
In getDataFromCatsApi add a completion handler
func getDataFromCatsApi(completion: #escaping (Result<[Breed],Error>) -> Void ) {
let url = URL(string: "https://api.thecatapi.com/v1/breeds")
let task = URLSession.shared.dataTask(with: url!) { data, _ , error in
if let error = error { completion(.failure(error)); return }
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
completion(Result { try decoder.decode([Breed].self, from: data!) })
}
task.resume()
}
In MainVC declare a data source array
var cats = [Breed]()
Replace viewDidLoad with
override func viewDidLoad() {
super.viewDidLoad()
title = "Cats"
view.backgroundColor = .systemBackground
getDataFromCatsApi {[unowned self] result in
DispatchQueue.main.async {
switch result {
case .success(let breed):
self.cats = breed
self.tableView.reloadData()
case .failure(let error): print(error)
}
}
}
}
and the table view datasources methods with
extension MainVC: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cats.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell",
for: indexPath) as! CustomTableViewCell
let cat = cats[indexPath.row]
cell.nameLabel = cat.name
cell.originLabel = cat.origin
}
}
To load the pictures is beyond the scope of the question. There are libraries like SDWebImage or Kingfisher to load and cache images asynchronously.
I have attached the code please check
extension MainVC: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Breed.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell",
for: indexPath) as? CustomTableViewCell
cell.nameLabel.text = Breed[indexPath.row].name // see here
return cell ?? CustomTableViewCell()
}
}
am try to convert json data to table view for swift 5 and also alamofire 5.2 version I got my response data from server itz also covert json but the problem is I can't show my response data in table view
class ViewController: UIViewController, UITableViewDataSource {
struct User {
var buzzyuser_id:Int?
var buzzyuser_image:String?
var buzzyuser_username:String?
init(dic:[String: Any]) {
self.buzzyuser_id = dic["buzzyuser_id"] as? Int
self.buzzyuser_image = dic["buzzyuser_image"] as? String
self.buzzyuser_username = dic["buzzyuser_username"] as? String
}
}
#IBOutlet weak var TableView: UITableView!
private var users = [User] ()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
TableView.dataSource = self
apiload()
}
func apiload() {
let parameters: [String: Any] = ["userid": "1","start":"0"]
let url = "https://example.com/sample.php"
AF.request(url, method: .post, parameters: parameters).responseJSON { response in
switch response.result{
case .success:
//success, do anything
if let json = response.value as? [String: Any] {
for item in json {
// construct your model objects here
self.users.append(User(dic:json))
}
DispatchQueue.main.async {
self.TableView.reloadData()
}
}
break
case .failure:
return
}
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return users.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "customcell")
let text = users[indexPath.row]
return cell!
}
}
debug value showed but list viewed only empty rows I can't find the error.
your problem is here
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->
UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "customcell")
let text = users[indexPath.row]
return cell!
}
you are assigning the user value to the param "text" and then you are not assigning any value to the table view cell.
If you are trying... for example to show on the table the user "buzzyuser_username" then after
let text = user[indexPath.row]
you should add
cell?.textLabel?.text = text.buzzyuser_username
Also make sure you are registering the identifier "customcell" ... if you wish to load the cell from a xib file you can do it like this (note that with a xib file you can also create a custom subclass of UITableViewCell and make a tableview row with the user image id and username (that is what I think you are trying to archive)
self.table?.register(UINib.init(nibName: "YOUR_NIB_NAME", bundle: nil), forCellReuseIdentifier: "customcell")
And after registering the reuse identifier you can then use it on your table view and if you also have added a custom class to your identifier you can force it on your tableview datasource implementation
let cell = tableView.dequeueReusableCell(withIdentifier: "customcell") as! YOUR_CUSTOM_SUBCLASS
I am trying to make a IOS app that is a home automation thing. I am using TableViewCell to display information.
My problem is that I have no idea how to get JSON to an Array with struct because I have to have struct I think.
My JSON is:
[{"namea":"TV","statea":"up_tv"},{"namea":"test","statea":"test"}]
My code is:
struct cellData {
let nameLabel : String!
let stateLabel : String!
}
class Main: UITableViewController {
var array = [cellData]()
override func viewDidLoad() {
array = [cellData(nameLabel: "tv", stateLabel: "up_tv"),
cellData(nameLabel: "tv", stateLabel: "down_tv")]
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = Bundle.main.loadNibNamed("TableViewCell", owner: self, options: nil)?.first as! TableViewCell
cell.nameLabel.text = array[indexPath.row].nameLabel
cell.stateLabal.text = array[indexPath.row].stateLabel
return cell
}
You need jsonDecoder
struct cellData : Decodable {
let nameLabel : String
let stateLabel : String
enum CodingKeys:String,CodingKey {
case nameLabel = "namea"
case stateLabel = "statea"
}
}
//
let str = """
[{"namea":"TV","statea":"up_tv"},{"namea":"test","statea":"test"}]
"""
do {
let cellArr = try JSONDecoder().decode([cellData].self, from: str.data(using:.utf8)!)
print(cellArr) //// check this
} catch {
}
//
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "id") as TableViewCell
}
I am trying to populate the data from the external database using a PHP script, and I can see the data has been received in viewdidload(). But I am not able to see the data in the tableview.
I tried using the breakpoint, but no luck as my program does not reach to
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { ....}
Can you please suggest what I am not doing correctly.
import UIKit
class UsersViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var data: NSArray = []
#IBOutlet weak var listTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
data = dataOfJson(url: "http://kpstudio18.com/app/select.php")
print("data are as \(data)")
}
func dataOfJson(url: String) -> NSArray {
var data = NSData(contentsOf: NSURL(string: url)! as URL)
var error: NSError?
var jsonArray: NSArray = try! JSONSerialization.jsonObject(with: data! as Data, options: .mutableContainers) as! NSArray
return jsonArray
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if data.count != 0 {
return data.count
} else {
return 1
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: additionInfoCell = self.listTableView.dequeueReusableCell(withIdentifier: "customCell") as! additionInfoCell
let maindata = (data[indexPath.row] as! NSDictionary)
cell.name.text = maindata["name"] as? String
cell.info.text = maindata["id"] as? String
print("Cell Name is \(cell.name.text)")
print("Cell Info (id) is \(cell.info.text)")
return cell
}
}
yourtableview_name.registerNib(UINib(nibName: "customCell", bundle: nil), forCellReuseIdentifier: "customCell")
try this in viewdidload.if it works let me know.
You simply forgot to reload your table. In your viewDidLoad() method add the following line yourTableView.reloadData() and hopefully it will work.
Also, check if you registered your "CustomCell" as said above by RB1509
As i read in the documentation i can access single url in firebase storage like this:
`// Create a reference to the file you want to download
let starsRef = storageRef.child("images/stars.jpg")
// Fetch the download URL starsRef.downloadURL { url, error in
if let error = error {
// Handle any errors }
else {
// Get the download URL for 'images/stars.jpg'
} }`
However, i have many files there, so how can i skip giving direct path and instead iterate through all files in the given directory?
Thanks for tips.
DownloadURL takes single string at a time. In case you want to show all the files inside a folder to a tableview like me, here is the
full code:
import UIKit import Firebase
My very First View Controller-
class FolderList: UIViewController {
var folderList: [StorageReference]?
lazy var storage = Storage.storage()
#IBOutlet weak var tableView : UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.storage.reference().child("TestFolder").listAll(completion: {
(result,error) in
print("result is \(result)")
self.folderList = result.items
DispatchQueue.main.async {
self.tableView.reloadData()
}
})
} }
extension FolderList : UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return folderList?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "FolderListCell", for:
indexPath) as? FolderListCell else {return UITableViewCell()}
cell.itemName.text = folderList?[indexPath.row].name
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 64.0
} }
extension FolderList : UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
guard let downloadVC = storyBoard.instantiateViewController(withIdentifier:
"DownloadedItemView") as? DownloadedItemView else {
return
}
downloadVC.storageRef = folderList?[indexPath.row]
self.navigationController?.pushViewController(downloadVC, animated: true)
}
}
You each cell:
class FolderListCell: UITableViewCell {
#IBOutlet weak var itemName : UILabel!
}