Swift 3: Custom Cell not displaying data - ios

Im receiving a JSON array from php and trying to passing data to table view. However, my tableview does not display the data.
class test1ViewController: UIViewController , UITableViewDataSource, UITableViewDelegate {
var TableData:Array< String > = Array < String >()
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return TableData.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! testTableViewCell
cell.mylabel1.text = TableData[indexPath.row]
return cell
}
func get_data_from_url(_ link:String)
{
let url:URL = URL(string: link)!
let session = URLSession.shared
let request = NSMutableURLRequest(url: url)
request.httpMethod = "GET"
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
let task = session.dataTask(with: request as URLRequest, completionHandler: {
(
data, response, error) in
guard let _:Data = data, let _:URLResponse = response , error == nil else {
return
}
print(data!)
self.extract_json(data!)
})
task.resume()
}
func extract_json(_ data: Data)
{
let json: Any?
do
{
json = try JSONSerialization.jsonObject(with: data, options: [])
// print(json!)
}
catch
{
return
}
guard let data_list = json as? NSArray else
{
return
}
if let countries_list = json as? NSArray
{
for i in 0 ..< data_list.count
{
if let country_obj = countries_list[i] as? NSDictionary
{
if let name = country_obj["name"] as? String
{
if let age = country_obj["age"] as? String
{
TableData.append(name + age)
}
}
}
}
}
}
When the array gives initial values like
animals = ["hinno", "ali", "khalil"],
the values appear to custom cell, but when i take the data from a server and do the json conversion, nothing appears.

tableview.reloadData() any time you make changes to the array.

If reload Data of the collection or tableView doesn't work use that in Dispatch code like this
DispatchQueue.main.async {
yourTableViewName.reloadData()
}

Related

TableView doesnot show the data?

My tableView does not show the data. I am fetching the data through api and save it into separate class with initializers. But it does not the show on the tableView. How to resolve this issue. I am new to iOS. I know there is only one line of code problem somewhere.
I call api in viewDidLoad method.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
//fetch all expected visitor data
self.apiExpectedVisitor(strURL: urlViewExpectedVisitors)
self.expectedTableView.reloadData()
}
Function of API Method
func apiExpectedVisitor(strURL: String)
{
fetchedExpectedData = []
//URL
let myURL = URL(string: strURL)
//URL Request
let request = NSMutableURLRequest(url: myURL!)
request.httpMethod = "GET"
request.setValue("application/json", forHTTPHeaderField: "Accept")
let token = "Bearer " + strToken
request.addValue(token, forHTTPHeaderField: "Authorization")
let postTask = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in
print(response!)
guard error == nil else {
return
}
guard let data = data else {
return
}
do {
//create json object from data
if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: [Any]] {
print("POST Method :\(json)")
DispatchQueue.main.async {
for expectedVisitors in json["expected_visitors"]!
{
let eachData = expectedVisitors as! [String: Any]
let id = eachData["id"] as! Int
let name = "\(String(describing: eachData["name"]))"
let email = "\(String(describing: eachData["email"]))"
let phone = eachData["phone"] as! String
let verification_code = "\(String(describing: eachData["expected_visitor_verification_code"]))"
let qr_code = eachData["expected_visitor_qr_code"] as? String
let isVisited = eachData["is_visited"] as! Int
let company_id = eachData["company_id"] as! Int
let purpose = "\(String(describing: eachData["purpose"]))"
let meeting_date = eachData["meeting_date"] as! String
let meeting_time = eachData["meeting_time"] as! String
let created_at = eachData["created_at"] as! String
let updated_at = eachData["updated_at"] as! String
//Date.formatter(createdDate: createdDate)
if let department_id = eachData["department_id"] as? Int, let employee_id = eachData["employee_id"] as? Int, let location_id = eachData["location_id"] as? Int, let image = eachData["image"] as? String, let duration = eachData["duration"] as? String {
fetchedExpectedData.append(FetchedAllExpectedVisitors.init(id: id, name: name, email: email, phone: phone, department_id: department_id, employee_id: employee_id, location_id: location_id, image: image, verification_code: verification_code, qr_code: qr_code!, isVisited: isVisited, company_id: company_id, purpose: purpose, meeting_date: meeting_date, meeting_time: meeting_time, duration: duration, created_at: created_at, updated_at: updated_at))
self.expectedTableView.reloadData()
}
}
}
}
} catch let error {
print(error.localizedDescription)
}
}
postTask.resume()
}
TableView DataSource and Delegate Methods
func numberOfSections(in tableView: UITableView) -> Int {
return fetchedExpectedData.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ShowExpectedCell", for: indexPath) as! ShowExpectedTVCell
cell.lblDate.text = fetchedExpectedData[indexPath.section].created_at
cell.lblVisName.text = fetchedExpectedData[indexPath.section].name
print(fetchedExpectedData[indexPath.section].name)
for i in 0..<fetchedDepttData.count {
let department_id = fetchedDepttData[i].depttID
if fetchedExpectedData[indexPath.section].department_id == department_id
{
cell.lblDeptt.text = fetchedDepttData[i].depttName
}
}
for i in 0..<fetchedEmployeeData.count {
let employee_id = fetchedEmployeeData[i].empID
if fetchedExpectedData[indexPath.section].employee_id == employee_id
{
cell.lblEmpName.text = fetchedEmployeeData[i].name
}
}
return cell
}
Check below points:-
Make sure you registered tableview cell nib and added dataSource and Delegate.
You are reloading tableview after your fetchedExpectedData array filled
Just add the below code in viewDidLoad
expectedTableView.delegate = self
expectedTableView.datasource = self
also check if you have set UITableViewDelegate , UITableViewDataSource in starting of the controller
class Yourviewcontrollername: UIViewController,UITableViewDelegate,UITableViewDataSource
{
//Rest of the code
}
Also put breakpoint in all delegate methods and see if anything hits.

Putting JSON data into an array when using Alamofire

I am trying to retrieve data from my site, I am using Alamofire, how can I put that data into an array that I can use to populate my table view?
override func viewDidLoad() {
super.viewDidLoad()
Alamofire.request("http://lytestech.ga/api/lytes/get_movies/").responseJSON { response in
if let json = response.result.value {
print("JSON: \(json)") // serialized json response
let res = json as! NSDictionary
let movies = res["movies"] as! NSArray
// movieTitles = movies["movie_desc"]
let movieTitles: [String] = movies["movietitile"] as! String
print (movies)
print (movieTitles)
}
if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) {
print("Data: \(utf8Text)") // original server data as UTF8 string
}
}
}
json data
JSON: {
movies = (
{
id = 66;
"movie_desc" = "spiders bite";
movietitile = spiderman;
},
{
id = 64;
"movie_desc" = horror;
movietitile = mummy;
}
);
status = ok;
}
(
{
id = 66;
"movie_desc" = "spiders bite";
movietitile = spiderman;
},
{
id = 64;
"movie_desc" = horror;
movietitile = mummy;
}
)
Store movies in movies NSArray
var movies = NSArray()
After that in cellForRowAt method you can display data like this.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "Identifier") as! YouCustomCell
let movieDetail = movies[indexPath.row] as! NSDictionary
cell.lblMovieName.text = movieDetail.value(forKey: "movietitile") as? String
return cell
}
Note: - This is just code skeleton, you can use as per your custom cell and Outlets
var movies:[Dictionary<String,AnyObject>] = [] // Makes movies array global
movies = res["movies"] // and tableview reload
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let identifier = "cell"
let cell = tableView.dequeueReusableCell(withIdentifier: identifier) ??
UITableViewCell(style: .default, reuseIdentifier: identifier)
cell.textLabel!.text = movies[indexPath.row]["movietitile"] as? String
return cell
}
func demo()
{
let str : String = "http://lytestech.ga/api/lytes/get_movies/"
let url = NSURL(string:str)
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
Alamofire.request(request)
.responseString { response in
switch (response.result) {
case .Success(let JSON):
let data = JSON.dataUsingEncoding(NSUTF8StringEncoding)!
do {
let responseString = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? [String:AnyObject]
// print(responseString!)
self.movieName = []
self.desc = []
let arr = responseString!["movies"] as! NSArray
for j in 0..<arr.count{
let dic = arr[j] as! NSMutableDictionary
self.movieName.addObject(dic.valueForKey("movietitile")!)
self.desc.addObject(dic.valueForKey("movie_desc")!)
}
self.removeIndicator()
self.contactTable.reloadData()
} catch _ as NSError {
//print(error)
}
break
case .Failure:
print("FAILURE")
self.removeIndicator()
break
}
}
}
Convert your response Data into Dictionary
let dictionary: Dictionary? = NSKeyedUnarchiver.unarchiveObject(with: response.data) as! [String : Any]
Extract your Array from Dictionary , there is key name movies
if let arryMovies1 = dictionary["movies"] as? [[String:Any]] {
print (arryMovies1);
// Now your have your Array
// You can Populate into UItableView
// when your array is modified than you have to reload the tableData
self.arryMovies=arryMovies1
self.tableView.reloadData()
}
In your cellForRowAtIndexPath for populating in list view
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "you_cell_identifre") as! UITableCell
let dicMovie = self.arryMovies[indexPath.row] as! NSDictionary
cell.lableTitle.text = dicMovie.value(forKey: "movietitile") as? String
return cell
}
I hope this will help you

pass json id from one table view controller into another table view controller in swift 3

I already new in swift 3 and objetive c, right now I am stuck into how can I pass the id of each row to another table view controller when the user tap in the row the user want to go.
Here is the json data firstFile:
[
{"id_categoria":"1","totalRows":"323","nombre_categoria":"Cirug\u00eda"},
{"id_categoria":"2","totalRows":"312","nombre_categoria":"Med Interna"},
{"id_categoria":"3","totalRows":"6","nombre_categoria":"Anatomia"},
{"id_categoria":"4","totalRows":"24","nombre_categoria":"Anestesiologia"},
...]
Here is my first table view controller:
import UIKit
class CatMedVC: UIViewController, UITableViewDataSource {
#IBAction func volver(_ sender: Any) { }
#IBOutlet weak var listaCategoria: UITableView!
var fetchedCategoria = [Categoria]()
override func viewDidLoad() {
super.viewDidLoad()
listaCategoria.dataSource = self
parseData()
}
override var prefersStatusBarHidden: Bool{
return true
}
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fetchedCategoria.count
}
public func tableView(_ tableView: UITableView, cellForRowAt IndexPath: IndexPath) ->
UITableViewCell {
let cell = listaCategoria.dequeueReusableCell(withIdentifier: "cell")
cell?.textLabel?.text = fetchedCategoria[IndexPath.row].esp
cell?.detailTextLabel?.text = fetchedCategoria [IndexPath.row].totalRows
return cell!
}
func parseData() {
let url = "http://www.url.com/firstFile.php" //in json format
var request = URLRequest(url: URL(string: url)!)
request.httpMethod = "GET"
let configuration = URLSessionConfiguration.default
let session = URLSession(configuration: configuration, delegate: nil, delegateQueue: OperationQueue.main)
let task = session.dataTask(with: request) { (data, response, error) in
if(error != nil) {
print("Error")
}
else {
do {
let fetchedData = try JSONSerialization.jsonObject(with:data!, options: .mutableLeaves) as! NSArray
//print(fetchedData)
for eachFetchedCategoria in fetchedData {
let eachCategoria = eachFetchedCategoria as! [String : Any]
let nombre_categoria = eachCategoria["nombre_categoria"] as! String
let totalRows = eachCategoria["totalRows"] as! String
let id_categoria = eachCategoria["id_categoria"] as! String
self.fetchedCategoria.append(Categoria(nombre_categoria: nombre_categoria, totalRows: totalRows, id_categoria: id_categoria))
}
//print(self.fetchedCategoria)
self.listaCategoria.reloadData()
}
catch {
print("Error 2")
}
}
}
task.resume()
}
}
class Categoria {
var nombre_categoria : String
var totalRows : String
var id_categoria : String
init(nombre_categoria : String, totalRows : String, id_categoria : String) {
self.nombre_categoria = nombre_categoria
self.totalRows = totalRows
self.id_categoria = id_categoria
}
}
So I need pass the id_categoria String into the another table view to show the data for the id selected previously...here I don't know how to do it...I have the json file waiting for the id selected previously..but I don't know how to catch it into the url
Here the second table view:
import UIKit
class EspMedVC: UITableViewController {
var TableData:Array< String > = Array < String >()
var EspecialidadArray = [String]()
#IBAction func volver(_ sender: Any) {
}
override func viewDidLoad() {
super.viewDidLoad()
get_data_from_url("http://www.url.com/secondFile.php?id=") // Here I need to put the id_categoria String in json format
}
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: "cell2", for: indexPath)
cell.textLabel?.text = TableData[indexPath.row]
return cell
}
func get_data_from_url(_ link:String)
{
let url:URL = URL(string: link)!
let session = URLSession.shared
let request = NSMutableURLRequest(url: url)
request.httpMethod = "GET"
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
let task = session.dataTask(with: request as URLRequest, completionHandler: {
(
data, response, error) in
guard let _:Data = data, let _:URLResponse = response , error == nil else {
return
}
self.extract_json(data!)
})
task.resume()
}
func extract_json(_ data: Data)
{
let json: Any?
do
{
json = try JSONSerialization.jsonObject(with: data, options: [])
}
catch
{
return
}
guard let data_list = json as? NSArray else
{
return
}
if let nombre_especialidad = json as? NSArray
{
for i in 0 ..< data_list.count
{
if let nombre_esp_obj = nombre_especialidad[i] as? NSDictionary
{
if let nombre_especialidad = nombre_esp_obj["subesp"] as? String
{
if let totalRows = nombre_esp_obj["totalRows"] as? String
{
TableData.append(nombre_especialidad + " [" + totalRows + "]")
}
}
}
}
}
DispatchQueue.main.async(execute: {self.do_table_refresh()})
}
func do_table_refresh()
{
self.tableView.reloadData()
}
}
This is a rough guide, please search for the methods in the documentation or here at other questions inside stackoverflow.
1) Add a variable inside your EspMedVC that will hold the "id_categoria String" that should be displayed.
2) Add a variable inside your CatMedVC that will hold the "id_categoria String" that the user selected.
3) Implement the "didSelectRow" delegate method from your tableview inside the "CatMedVC", inside this method you should set the variable set on step 2.
4) Implement the "prepareForSegue" method inside your CatMedVC, inside the the implementation you should retrieve the destination VC, cast it to "EspMedVC" and set the variable from step 1.
5) On the "viewDidLoad" from EspMedVC you can now use the variable set on step 2 to query your JSON and update the table view accordingly.

Connecting JSON from external server to Swift tableView

I am new to Swift, and am trying to create a table that reads JSON data from my website. I followed some tutorials, and was able to get my code to work with a table controller. Now I'm trying to use a view controller with a table view inside, so I can have more customization. My problem is, I can't get the data to actually show up when I try to use my new code.
This is what I have in my viewController.swift:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var TableData:Array< String > = Array < String >()
override func viewDidLoad() {
super.viewDidLoad()
get_data_from_url("http://www.stevenbunting.org/Alliris/service.php")
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return TableData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = TableData[indexPath.row]
return cell
}
func get_data_from_url(_ link:String)
{
let url:URL = URL(string: link)!
let session = URLSession.shared
let request = NSMutableURLRequest(url: url)
request.httpMethod = "GET"
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
let task = session.dataTask(with: request as URLRequest, completionHandler: {
(
data, response, error) in
guard let _:Data = data, let _:URLResponse = response , error == nil else {
return
}
self.extract_json(data!)
})
task.resume()
}
func extract_json(_ data: Data)
{
let json: Any?
do
{
json = try JSONSerialization.jsonObject(with: data, options: [])
}
catch
{
return
}
guard let data_list = json as? NSArray else
{
return
}
if let countries_list = json as? NSArray
{
for i in 0 ..< data_list.count
{
if let country_obj = countries_list[i] as? NSDictionary
{
if let country_name = country_obj["user"] as? String
{
if let country_code = country_obj["friendlist"] as? String
{
TableData.append(country_name + " [" + country_code + "]")
}
}
}
}
}
DispatchQueue.main.async(execute: {self.do_table_refresh()
})
}
func do_table_refresh()
{
self.tableView.reloadData()
}
}
Probably you didn't set the tableView's dataSource. To do this, implement the UITableViewDataSource-protocol in the ViewController-class and set the tableView's dataSource-property to self in the viewDidLoad(), for example:
class ViewController: UIViewController, UITableViewDataSource {
// ...
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
// ...
}
//...
}
Oh, and don't forget about the Apple Transport Security-settings, otherwise you won't see anything as iOS doesn't allow HTTP anymore, you have use HTTPS. The right way to handle this is to get an SSL-Certificate for your domain.
The quick'n'dirty and absolutely not recommended way is to disable ATS or to set an exception for certain, trustworthy domains.

In Swift, tableView data loaded from JSON only loads 80% of the time

I'm populating my tableView with JSON data, most of the time the data shows but for some strange reason other times it doesn't. I tested the JSON data in Chrome and the info is there. I also made print statements to print the info after it has downloaded and it appears to download correctly. I can't figure out why 80% of the time the data populates the tableView correctly and 20% of the time it doesn't. Here is a sample of my code, there are many more cells but I shortened it to 2 for this example:
var task : NSURLSessionTask?
var newURL : String?
var bannerArray: [String] = []
var overViewArray: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
getJSON(newURL!)
}
func getJSON (urlString: String) {
let url = NSURL(string: urlString)!
let session = NSURLSession.sharedSession()
task = session.dataTaskWithURL(url) {(data, response, error) in
dispatch_async(dispatch_get_main_queue()) {
if (error == nil) {
self.updateDetailShowInfo(data)
}
else {
"Not getting JSON"
}
}
}
task!.resume()
}
func updateDetailShowInfo (data: NSData!) {
do {
let jsonResult = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
guard let banner = jsonResult["banner"] as? String,
let overview = jsonResult["overview"] as? String
else { return }
_ = ""
print(overview)
bannerArray.append(banner)
overViewArray.append(overview)
}
catch {
print("It ain't working")
}
self.DetailTvTableView.reloadData()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0: return bannerArray.count
case 1: return overViewArray.count
default: fatalError("Unknown Selection")
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
switch indexPath.section {
case 0:
let cell = tableView.dequeueReusableCellWithIdentifier("bannerCell", forIndexPath: indexPath) as! BannerCell
cell.bannerImage.sd_setImageWithURL(NSURL(string: bannerArray[indexPath.row]))
self.DetailTvTableView.rowHeight = 100
DetailTvTableView.allowsSelection = false
return cell
case 1:
let cell = tableView.dequeueReusableCellWithIdentifier("overviewCell", forIndexPath: indexPath) as! OverviewCell
let overViewText = overViewArray[indexPath.row]
if overViewText != "" {
cell.overView.text = overViewText
} else {
cell.overView.text = "N/A"
}
self.DetailTvTableView.rowHeight = 200
print(overViewArray[indexPath.row])
return cell
default: ""
}
return cell
}
I'm just doing this off the web. And I think there are some errors. You need to debug them yourself.
Your understanding of fetching the JSON and GCD is totally wrong. I believe these codes you got somewhere off the web. Go read up what is dispatch_async.
Basically, you need to create session to fetch JSON data, which you have done it correctly, however, within the NSJSONSerialization, you need to store them in a variable and append it to your array. This is fetched asynchronously. Your dispatch_async will reload data serially.
func getJSON (urlString: String) {
let url = NSURL(string: urlString)!
let session = NSURLSession.sharedSession()
task = session.dataTaskWithURL(url) {(data, response, error) in
let jsonResult = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
guard let banner = jsonResult["banner"] as? String,
let overview = jsonResult["overview"] as? String
bannerArray.append(banner)
overViewArray.append(overview)
} dispatch_async(dispatch_get_main_queue()) {
if (error == nil) {
self.DetailTvTableView.reloadData()
}
else {
"Not getting JSON"
}
}
catch {
print("It ain't working")
}
}
}
task!.resume()
}

Resources