SwiftyJSON and Alamofire data parsing in TableView (iOS, Swift 4) - ios

When I run my project I am just able to get only tableView but datas are not fetched its blank. The struct codable and view controller codes were as follows. Please help me in viewing the datas in my tableView cells using alamofire and SwiftyJSON,
class Loads: Codable {
let loads: [Load]
init(loads: [Load]) {
self.loads = loads
}
}
class Load: Codable {
let id: String
let ad_title: String
let ad_description:String
let ad_price: String
let ad_post_date: String
let image1: String
init(ad_title: String, ad_description: String, ad_price: String, ad_post_date: String, image1: String) {
self.ad_title = ad_title
self.ad_description = ad_description
self.ad_price = ad_price
self.ad_post_date = ad_post_date
self.image1 = image1
}
}
View Controller codes:
import UIKit
import SwiftyJSON
import Alamofire
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var loads = [Load]()
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
downloadJson()
self.tableView.reloadData()
tableView.delegate = self
tableView.dataSource = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection
section: Int) -> Int {
return loads.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath:
IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "LoadCell") as? LoadCell else { return UITableViewCell() }
cell.labelA.text = loads[indexPath.row].ad_title
cell.labelB.text = loads[indexPath.row].ad_price
cell.labelC.text = loads[indexPath.row].ad_description
cell.labelD.text = loads[indexPath.row].ad_post_date
if let imageURL = URL(string: loads[indexPath.row].image1) {
DispatchQueue.global().async {
let data = try? Data(contentsOf: imageURL)
if let data = data {
let image = UIImage(data: data)
DispatchQueue.main.async {
cell.loadImage.image = image
}
}
}
}
return cell
}
func downloadJson(){
Alamofire.request("https://alot.ae/api/classifiedcomputerlaptop.php").responseJSON { response in
if let value = response.result.value {
let json = JSON(value)
//Printing strings from a JSON Dictionary
print(json[0]["ad_title"].stringValue)
print(json[0]["ad_price"].stringValue)
print(json[0]["ad_description"].stringValue)
print(json[0]["ad_post_date"].stringValue)
print(json[0]["image1"].stringValue)
}
self.tableView.reloadData()
}
self.tableView.reloadData()
}
}
I am using xcode9, swift 4.

datas are not fetched its blank
Your code does not seem to update var loads by downloaded data, that is why you just get blank table view. So, you need to assign fetched data to var loads.
Here is sample:
Alamofire.request("https://alot.ae/api/classifiedcomputerlaptop.php").responseJSON { response in
// you should assign response data into var loads here
if let data = response.data {
do {
self.loads = try JSONDecoder().decode([Load].self, from: data)
} catch {
// exception
}
}
}
And after that, self.tableView.reloadData().
PS: Of course I don't know your response JSON format and your source code overall, so it might not be a directory answer to your question, but I hope it will help!

At first glance, the url looks faulty to me. https is typed twice, please remove once in below line.
Change this :
Alamofire.request("https:https://alot.ae/api/classifiedcomputerlaptop.php").responseJSON
to :
Alamofire.request("https://alot.ae/api/classifiedcomputerlaptop.php").responseJSON

First off, your...
struct codable
... is not a struct at all, it is a class. change that to an actual struct.
Second, you start downloading before your delegate and datasource are set to the tableview.
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
downloadJson()
}
Thirdly, you are using Alamofire for a simple GET request, but you ignore the fact of asyncronous loading of images for a cell, which you do with Data. I'd suggest to use AlamoFireImageDownloader or remote AlamoFire all together. Using URLSession is just as easy:
private func request(url: URL, completionHandler: #escaping ((Data?, URLResponse?, Error?) -> Void)) {
var request = URLRequest(url: url)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request, completionHandler: completionHandler)
task.resume()
}
Fourth, I don't believe you need the loads codable.
Just an extra reminder, depending on the amount of Loads you'll have in your table, you will get problems with the loading of your images. The closures are not guaranteed to finish in order, but when they do they will update the cell regardless to whether the cell is already reused for another Load or not. Just FYI.

Related

Swift, fetch TableView from JSON and save it into array

i'm trying to do some simple things here, but i'm struggling a bit as i'm a beginner.
So basically i have a JSON file link to use to populate my tableview with 2 sections. Each cell have a "Favourite button".
i've tried many way to save my array with UserDefault with no luck.
What i wish to achieve:
When the "Favourite button" is pressed, i wish to move the cell to the other section
Save and retrieve those 2 array using UserDefault
I'm open to hear any suggestion also any other differs approach, as i'm sure there is some better one.
I will upload here some code, but also the link for the full project in Git so you can check better (https://github.com/Passeric/UserTableview.git)
I really appreciate any help.
The JSON i'm using:
{
"User": [
{
"Name": "John",
"Age": "34"
},{
"Name": "Sara",
"Age": "19"
}.......]}
My Struct:
class User: Codable {
let user: [UserDetails]
enum CodingKeys: String, CodingKey {
case user = "User"
}
init(user: [UserDetails]) {
self.user = user
}
}
class UserDetails: Codable {
let name: String
let age: String
enum CodingKeys: String, CodingKey {
case name = "Name"
case age = "Age"
}
init(name: String, age: String) {
self.name = name
self.age = age
}
}
And my ViewController:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var arrayDefault = [UserDetails]()
var arrayFavourite = [UserDetails]()
var sec: [Int:[UserDetails]] = [:]
var Default = UserDefaults.standard
#IBOutlet weak var myTableview: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.myTableview.dataSource = self
self.myTableview.delegate = self
DownloadJSON()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
sec = [0 : arrayFavourite, 1 : arrayDefault]
return (sec[section]?.count)!
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let dataRef = arrayDefault[indexPath.row]
let cel: MyCell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as! MyCell
cel.NameLabel.text = dataRef.name
cel.AgeLabel.text = dataRef.age
let imgFav = UIImage(systemName: "star")
let b = imgFav?.withRenderingMode(.alwaysOriginal)
cel.FavButton.setImage(b, for: .normal)
return cel
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
func DownloadJSON() {
let urlll = URL(string: "https://pastebin.com/raw/Wufivqmq")
guard let downloadURL = urlll else { return }
URLSession.shared.dataTask(with: downloadURL) { data, urlResponse, error in
guard let data = data, error == nil, urlResponse != nil else {
print("something is wrong")
return
}
print("downloaded")
do
{
let decoder = JSONDecoder()
let downloadeduser = try decoder.decode(User.self, from: data)
self.arrayDefault.removeAll()
self.arrayDefault.append(contentsOf: downloadeduser.user)
DispatchQueue.main.async {
print("data saved")
self.myTableview.reloadData()
}
} catch {
print(error)
}
}.resume()
}
#IBAction func RefreshButton(_ sender: Any) {
// Here i wish to refresh the table view (so the current saved array) with the updated JSON
// For example if i update the "Age" in the original JSON
// But i don't want to lose the user preference for the "Favourite"
}
}
As you can see is not a big deal thing, but i can't figure out how to properly save and retrive the array, and then move the cell (by the index path) to the other array.
This is the link for the full project: https://github.com/Passeric/UserTableview.git
Thanks again to anyone who will help.❤️
I would make a few changes:
Clean up your data model. Currently you are storing the data as both two arrays and a dictionary. There are minor pros and cons to each approach, but in the grand scheme of things it doesn't really matter which one you use, just pick one. Personally, as a beginner, I would go with two arrays.
Don't change your data model in the data source. Currently you are creating the sec dictionary in the tableView:numberOfRowsInSection function. If you want to keep using sec then create it as the same time you load the data initially. Or, as mentioned above, just remove sec completely.
Assuming you've made the above changes, moving a user to the favorites section is as simple as removing the user from the default list, adding it to the favorites list, and telling the list that the data has changed:
func makeFavorite(index:IndexPath) {
let user = arrayDefault[index.row]
arrayDefault.remove(at: index.row)
arrayFavourite.append(user)
//This updates the entire list. You might want to use moveRow(at:to:) in order to animate the change
tableView.reloadData()
}
When it comes to converting your data model to/from json, you're already most of the way there by conforming to Codable. To load from json:
if let jsonData = UserDefaults.standard.string(forKey: "userKey").data(using: .utf8) {
let decoder = JSONDecoder()
if let user = try? decoder.decode(User.self, from: jsonData) {
//Do something with user here...
}
}
And to output to json:
let encoder = JSONEncoder()
if let data = try? encoder.encode(user),
let jsonString = String(decoding: data, as: .utf8) {
UserDefaults.standard.setValue(jsonString, forKey: "userKey")
}
Do the same thing with the list of favorites (using a different key).

Why does my TableView only show the last image loaded in every cell? (swift)

The problem I have have at the moment is properly displaying images in a tableView cell. My images are saved to Firebase, and I can easily retrieve both images.
When I try to display each image in its own table view cell they quickly load both images and the end result is the last image displaying in both cells instead of two different images.
I believe the issue is either with my cellForRowAt IndexPath or how I am calling the data from Firebase.
This is my Main TableView View Controller
import UIKit
import Firebase
import FirebaseStorage
import FirebaseDatabase
class CardDesignViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
//passing a value to another page with thie var
var IdvalueTitle = ""
var db:Firestore!
//PropertiesCell2 is pointing to a swift file containing my dictionary for the outlets
var propertiesArray3 = [PropertiesCell2]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
extension CardDesignViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return propertiesArray3.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let spot = propertiesArray3[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "TableView2") as! TableView2
cell.app? = "\(spot.templateOption)"
cell.IDvalueHidden?.text = "\(spot.IDvalueHidden)"
cell.templateOption.layer.cornerRadius = 12
cell.templateOption.layer.masksToBounds = true
return cell
}
I have put my outlets for the cells into a file called "TableView2". This is where I call the data for the images from Firebase in a func called getTemplates() and use that within "var app: String!"
import Foundation
import UIKit
import Firebase
import FirebaseDatabase
import FirebaseStorage
class TableView2: UITableViewCell {
#IBOutlet weak var templateOption: UIImageView!
#IBOutlet weak var IDvalueHidden: UILabel!
func styleTheCells2(cells: Cell2) {
templateOption.image = cells.templateOption
IDvalueHidden.text = cells.IDvalueHidden
}
var app: String! {
didSet {
self.getTemplates()
}
}
func getTemplates() {
let db = Firestore.firestore()
db.collection("Card Templates").getDocuments { (snapshot, err) in
if err != nil {
return
} else {
for document in (snapshot?.documents)! {
if let picURL = document.data()["Template"] as? String {
let url = URL(string: picURL)
print(picURL)
DispatchQueue.global().async {
do{
let data = try Data(contentsOf: url!)
DispatchQueue.main.async {
self.templateOption.image = UIImage(data: data)
}
} catch {
}
}
}
}
}
}
}
I've attached a picture as well of the end result when I run this code. I get the same image in both cells however, when I look at the debug area I can see that both images were accessed twice.
This is my simulator when I run this code. Im looking to have two different images in the cells rather than the one picture in both:
My debugger shows both image urls being pulled twice consecutively and the last image pulled (the green image) shows in both cells:
You are fetching the images from Firebase Storage each time UITableViewCell is being presented via getTemplates() function
Since you have 2 images in Firebase, I am assuming 'propertiesArray3' has 2 elements in it.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return propertiesArray3.count
}
Each time it goes through the Firebase and prints out all the URLs in the db. As the numberOfRowsInSection is 2, the Image URL are being printed twice.
The for loop ends at the last element each time and sets the last URL as the image.
func getTemplates() {
let db = Firestore.firestore()
db.collection("Card Templates").getDocuments { (snapshot, err) in
if err != nil {
return
} else {
for document in (snapshot?.documents)! {
if let picURL = document.data()["Template"] as? String {
let url = URL(string: picURL)
print(picURL)
DispatchQueue.global().async {
do{
let data = try Data(contentsOf: url!)
DispatchQueue.main.async {
self.templateOption.image = UIImage(data: data)
}
} catch {
}
}
}
}
}
}
Hope it helps
For a basic approach to start with, you can try something like this -
Declare an array to store the URL
var urlArray: [URL] = []
Fetch the URLs in viewDidLoad()
let db = Firestore.firestore()
db.collection("Card Templates").getDocuments { (snapshot, err) in
if err != nil {
return
} else {
for document in (snapshot?.documents)! {
if let picURL = document.data()["Template"] as? String {
let url = URL(string: picURL)
// ADD ALL THE URLs TO THE NEW ARRAY
urlArray.append(url)
}
}
tableView.reloadData()
}
}
Remove getTemplates() from UITableViewCell
Edit the tableView Delegate
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return urlArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let spot = propertiesArray3[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "TableView2") as! TableView2
let url = urlArray[indexPath.row]
do{
let data = try Data(contentsOf: url!)
DispatchQueue.main.async {
cell.templateOption.image = UIImage(data: data)
}
} catch {
}
cell.app? = "\(spot.templateOption)"
cell.IDvalueHidden?.text = "\(spot.IDvalueHidden)"
cell.templateOption.layer.cornerRadius = 12
cell.templateOption.layer.masksToBounds = true
return cell
}
You most clear content based Views of cell in prepareForReuse function
override func prepareForReuse() {
super.prepareForReuse()
// remove image from imageView
templateOption.image = nil
}

How can I update UI using JSON data that I'm receiving from the server?

I'm using Swift Codable Protocol and receiving JSON data that I need to put into my labels and images, but it's not showing in my table view when I run the app.
Here's what my code look like
import UIKit
struct OfferList: Codable {
let data: [Int: CarItems]?
let status: String?
let count: Int? }
struct CarItems: Codable {
let id: String?
let image: URL?
let manufacturer: String?
let model: String?
let price_net: Int?
let price_old: Int?
let price_gross: Int?
let power_kw: String?
let power_ps: String?
let milage: String?
let fueltype: String? }
class OfferVC: UIViewController {
#IBOutlet weak var tableView: UITableView!
var viewModels = [CarItems]() {
didSet {
self.tableView.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
let urlString = "http://grandex.de/api/v1/de/offers"
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let data = data else { return }
guard err == nil else { return }
do {
let array: Any = try JSONSerialization.jsonObject(with: data, options: [.allowFragments])
print(array)
if let objects = try JSONDecoder().decode(OfferList.self, from: data).data {
objects.forEach({
print($0)
self.viewModels.append($1)
DispatchQueue.main.async {
self.tableView.reloadData()
}
})
}
} catch let jsonErr {
print(jsonErr)
}
}.resume()
} }
extension OfferVC: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModels.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "id") as! Cell
let vm = viewModels[indexPath.row]
cell.update(with: vm)
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 130
} }
class Cell: UITableViewCell {
#IBOutlet weak var carImage: UIImageView?
#IBOutlet weak var title: UILabel?
#IBOutlet weak var fuelType: UILabel?
func update(with item: CarItems) {
title?.text = item.manufacturer
fuelType?.text = item.fueltype
} }
I'm expecting it to change my labels, but in simulator table view is empty.
Please advice what am I doing wrong.
Also could someone tell me how can I update image with JSON data?
Any help would be much appreciated! Thanks in advance!!
There are two major errors in the structs, data is [CarItems] and priceNet is Double.
You must get the error
Type 'Dictionary' mismatch: Expected to decode Dictionary but found an array instead.
Declare all struct members non-optional and name them camelCased
struct OfferList: Decodable {
let data: [CarItems]
let status: String
let count: Int
}
struct CarItems: Decodable {
let id: String
let image: URL
let manufacturer: String
let model: String
let priceNet: Double
let priceOld: Int
let priceGross: Int
let powerKw: String
let powerPs: String
let milage: String
let fueltype: String
}
Declare the data source array without the property observer
var viewModels = [CarItems]()
Decode the JSON
URLSession.shared.dataTask(with: url) { (data, _, error) in
if let error = error { print(error); return }
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let result = try decoder.decode(OfferList.self, from: data!)
self.viewModels = result.data
DispatchQueue.main.async {
self.tableView.reloadData()
}
} catch {
print(error)
}
}.resume()
Make sure that datasource and delegate of the tableview are connected to the view controller preferable in Interface Builder.
Add breakpoints in the table view data source and delegate function to make sure that there is data as expected from the server. Also, I see that in your CustomCell, the outlets are of the optional type which should not be. Additionally check the update(with item: CarItems) function to see if the label and the expected value exists using a breakpoint.
You need to add below lines of code in viewDid load.
tableView.dataSource = self
tableView.delegate = self
Hope it may help you.

Swift 3: Preload data before putting it into UITableView

I have an app that will fetch exactly 100 strings from an API and place them into a UITableView. I wish to first preload the data into an array and then, once the array is fully populated with the 100 entries, load the data into the table.
Due to the asynchronous API call, it seems like I am unable to load data into the array before the table view starts populating its cells. Mainly, I am having difficulty getting the data out of the closure in the first place.
This is the API call defined in an APIAgent class:
func getAPIData(_ requestType: String, completionHandler: #escaping (Data) -> ()) {
let requestURL: URL = URL(string : baseURL + requestType)!
let currentSession = URLSession.shared
let task = currentSession.dataTask(with: requestURL) { (data, response, error) in
completionHandler(data!)
}
task.resume()
}
This is how the UITableView uses it:
protocol AsyncHelper {
func getData(data: Any)
}
class TableViewController: UITableViewController, AsyncHelper {
var dataEntries: [String] = []
func getData(data: Data) {
let entry: String = String(describing: data)
dataEntries.append(entry)
}
override func viewDidLoad() {
super.viewDidLoad()
for i in 1...100 {
apiAgent.getAPIData("entry" + String(i), entry: { entry in
self.getData(data: entry)
})
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "EntryCell", for: indexPath) as! EntryCell
let entry: String = dataEntries[indexPath.row] // index out of range error
DispatchQueue.main.async {
// add Strings to cell here
}
return cell
}
}
So it appears that the cells are being generated before data gets populated into the dataEntries array. How do I prevent the UITableView from generating the cells until dataEntries is populated.
If you are going to use a closure you won't need a protocol. You could change your networking code to:
var songData = [Data]
func getAPIData(_ requestType: String, completionHandler: #escaping ([Data]) -> ()) {
let requestURL: URL = URL(string : baseURL + requestType)!
let currentSession = URLSession.shared
let task = currentSession.dataTask(with: requestURL) { (data, response, error) in
songData.append(data!)
if (songData.count == 100) {
completionHandler(songData)
}
}
task.resume()
}
This will make sure that your getData() and tableView.reloadData() will only be called once all 100 of your data elements have been loaded.
FYI - tableView.reloadData() will reload pretty much everything that has to deal with your table view. Your numberOfRows, numberOfSections, and cellForRow will all be called again. This will create the tableView over again using the updated dataEntries values
Try this :
override func viewDidLoad() {
super.viewDidLoad()
tblView.delegate = nil
tblView.dataSource = nil
for i in 1...100 {
apiAgent.getAPIData("entry" + String(i), entry: { entry in
self.getData(data: entry)
tblView.delegate = self
tblView.dataSource = self
tblView.reloadData()
})
}
}

Parsing JSON into tableview

I am receiving a JSON file from a remote server and I can display the result in a label. The JSON data is working fine when I call function processJSONData() and the tableview works fine with a simple array. How can I incorporate both to display the result from the JSON file in the tableview? Kindly look at the code below and edit. Many thanks:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var countryLabel: UILabel!
#IBOutlet weak var capitalLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
//processJSONData()
self.myTableView.registerClass(UITableViewCell.self,forCellReuseIdentifier: "cell")
self.myTableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func processJSONData(){
let urlPath = "http://dubaisinan.host22.com/service1.php"
let url : NSURL = NSURL(string: urlPath)!
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url,completionHandler: {(data, respose, error) -> Void in
if error != nil {
println(error)
}
else {
self.abc(data)
}
})
task.resume()
}
func abc(data:NSData)
{
var parseError: NSError?
let result:AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &parseError);
if(parseError == nil){
if let dictResult = result as? NSArray{
dispatch_async(dispatch_get_main_queue()) {
self.countryLabel.text = dictResult[2]["Capital"] as? String
}
}
}
}
#IBOutlet weak var myTableView: UITableView!
var items = ["One","Two", "Three","Four"]
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = self.myTableView
.dequeueReusableCellWithIdentifier("cell") as UITableViewCell
cell.textLabel?.text = self.items[indexPath.row]
return cell
}
}
I don't see you assign your parsing result to global "items" and reload tableview with new data anywhere.
could be done here
if let dictResult = result as? NSArray{
self.items = dictResult
self.myTableView.reloadData()
///the rest of the code
}
You have to save the JSON data into a class-level variable, which you will define outside of any function, similar to how you defined "items". Assuming you have a list of countries with the capital of each, this might look like so:
var countryAndCapitalData = [(country: String, capital: String)]()
This could be improved by first defining a struct to contain your data:
struct CountryInfo
{
name: String
capital: String
init(name:String, capital:String)
{
self.name = name
self.capital = capital
}
}
which lets you define your data array as an array of CountryInfo:
var countryAndCapitalData = [CountryInfo]()
Then in your "abc" function (which I insist you rename to something like processCountryData), store the pairs of country name + capital name strings in countryAndCapitalData. For example:
countryAndCapitalData.append(CountryInfo(countryName, capitalName))
Use a For loop to loop through values in dictResult. Creating countryName and capitalName depends on the structure of your JSON, but from your example it might look like this:
for countryDictionary in dictResult[2]
{
if let countryName = countryDictionary["country"], let capitalName = countryDictionary["capital"]
{
countryAndCapitalData.append(CountryInfo(countryName, capitalName))
}
}
Then in tableView.cellForRowAtIndexPath, populate the cell label(s) with countryAndCapitalData[indexPath.row].name and countryAndCapitalData[indexPath.row].capital.
And finally, be sure to reload the table after the loop (thanks Eugene):
dispatch_async(dispatch_get_main_queue()) {
self.myTableView.reloadData()
}
Apologies for any compilation errors, as I'm typing this from a Windows machine.
You should update your items property in abc method call and then refresh the table:
func abc(data: NSData) {
// Do something with data
items = .. // processed data
}
var items: [String]? {
didSet {
NSOperationQueue.mainQueue.addOperationWithBlock {
self.tableView.reloadData()
}
}
}

Resources