Home > database >  How to send Json Data to Table View Array? Swift
How to send Json Data to Table View Array? Swift

Time:11-08

I've been researching and wrecking my brain attempting to get my JSON data to load into my tableview. I've tried placing the data in a Variable & I'm able to see the data in the console when I print it, however unable to push it to my table view.

Am I doing something wrong on the data page or am I not properly accessing the data within the loop?

I've tried putting the loop in the viewdidload but haven't been successful either.

// ViewController

import Foundation
import UIKit
import SDWebImage

class EntertainmentViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    var A = EntertainmentApi()
    
    var data = [EntertainmentPageData]()
    var AA = EntertainmentApi().userFeedPosts
    @IBOutlet weak var entPostTableView: UITableView!
   
    
    override func viewDidLoad() {
        
        func showTable() {
            
        }
        entPostTableView.register(EntertainmentViewrTableViewCell.nib(), forCellReuseIdentifier: EntertainmentViewrTableViewCell.identifier)
        entPostTableView.delegate = self
        entPostTableView.dataSource = self
        super.viewDidLoad()
        
        
        DispatchQueue.main.async {
        
        self.entPostTableView.reloadData()
        }
    }
    
    
    
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let customCell1 = tableView.dequeueReusableCell(withIdentifier: EntertainmentViewrTableViewCell.identifier, for: indexPath) as! EntertainmentViewrTableViewCell
        customCell1.profileDisplayName.text = AA[indexPath.row].postDisplayName
            self.AA.forEach({ (EntertainmentPageData) in
                customCell1.configue(with: EntertainmentPageData.postDisplayName, PostImage: EntertainmentPageData.imageURLString, PostDescription: EntertainmentPageData.postDescription)
            })
                    
                            
        
           
            
 
        return customCell1
            
        
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 2
    }
    func item(for index: Int) -> EntertainmentPageData {
        return data[index] 
    }
    func numberOfItems() -> Int {
        return data.count
    }
}
//Data

import SwiftUI
import SDWebImage

public protocol EntertainmentPagePostItem {
    /// The image for the card.
    var imageURLString: String { get }
    
    /// Rating from 0 to 5. If set to nil, rating view will not be displayed for the card.
    var postDescription: String? { get }
    
    /// Will be displayed in the title view below the card.
    var postDisplayName: String { get }
}

public protocol EntertainmentPagePostDataSource: class {
    /// CardSliderItem for the card at given index, counting from the top.
    func item(for index: Int) -> EntertainmentPagePostItem
    
    /// Total number of cards.
    func numberOfItems() -> Int
}
struct HomePagePost: Codable {
    var displayName: String
    var cityStatus: String
    var displayDescription: String
    var displayImageURL: String
    var lookingFor: String
    var profileImager1: String?
    var profileImager2: String?
    var profileImager3: String?
    var profileImager4: String?
    
}

struct EntertainmentPageData: Codable {
    let postDisplayName: String
    let imageURLString: String
    let postDescription: String?
    
}
public class entPostFly: Codable {
    let postDisplayName, imageURLString, postDescription: String
}
struct eItem: EntertainmentPagePostItem {
    var postDisplayName: String
    var imageURLString: String
    var postDescription: String?
}

public class EntertainmentApi {
    
    var userFeedPosts = [EntertainmentPageData]()
    
    init() {
        load()
    }
    
    func load() {
        
        guard let apiURL = URL(string: "https://api.quickques.com/....") else {
        return
    }
    
        let task: () = URLSession.shared.dataTask(with: apiURL) { Data, apiResponse, error in
            
            guard let Data = Data else { return }
            
            do {
                let entPostData = try JSONDecoder().decode([EntertainmentPageData].self, from: Data)
                self.userFeedPosts = entPostData
                
            }
            catch {
                let error = error
                print(error.localizedDescription)
            }
            
        }.resume()
        
    }
    
    
    func getFeedPosts(completion: @escaping ([EntertainmentPageData]) -> () ) {
        guard let apiURL = URL(string: "https://api.quickques.com/....") else {
        return
    }
    
        let task: () = URLSession.shared.dataTask(with: apiURL) { Data, apiResponse, error in
            
            guard let Data = Data else { return }
            
            do {
                let entPostData = try JSONDecoder().decode([EntertainmentPageData].self, from: Data)
                completion(entPostData)
            }
            catch {
                let error = error
                print(error.localizedDescription)
            }
            
        }.resume()
    
}
    
    
}

class Api {
    
    func getHomePagePosts(completion: @escaping ([HomePagePost]) -> Void ) {
        guard let apiURL = URL(string: "https://api.quickques.com/.....") else {
            return
        }
        
        let task: () = URLSession.shared.dataTask(with: apiURL) { Data, apiResponse, error in
            
            guard let Data = Data else { return }
            
            do {
                let homePostData = try JSONDecoder().decode([HomePagePost].self, from: Data)
                
                completion(homePostData)
            }
            catch {
                let error = error
                print(error.localizedDescription)
            }
            
        }.resume()
       
    }
    
    
    func getImageData(from url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> ()) {
        URLSession.shared.dataTask(with: url, completionHandler: completion).resume()
    }
    
    
    
}

func getTopMostViewController() -> UIViewController? {
    var topMostViewController = UIApplication.shared.keyWindow?.rootViewController

    while let presentedViewController = topMostViewController?.presentedViewController {
        topMostViewController = presentedViewController
    }

    return topMostViewController
}

CodePudding user response:

First you have an empty function showTable inside your viewDidLoad - This does nothing. Presumably it is something hanging around from your various attempts. Delete that.

As you have probably worked out, your network fetch operation is going to occur asynchronously and you need to reload the table view once the data has been fetched.

You have some code in viewDidLoad that kind of tries to do this, but it isn't related to the fetch operation. It is just dispatched asynchronously on the next run loop cycle; This is probably still before the data has been fetched.

However, even if the data has been fetched, it won't show up because you are assigning userFeedPosts from a second instance of your API object to AA at initialisation time. This array is empty and will remain empty since Swift arrays are value types, not reference types. When userFeedPosts is updated, AA will hold the original empty array.

To load the data you need to

  1. Start a load operation when the view loads
  2. Pass a completion handler to that load operation to be invoked when the load is complete
  3. Reload your table view with the new data
class EntertainmentViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
   
    var data = [EntertainmentPageData]()
    @IBOutlet weak var entPostTableView: UITableView!
    
    override func viewDidLoad() {
        
        entPostTableView.register(EntertainmentViewrTableViewCell.nib(), forCellReuseIdentifier: EntertainmentViewrTableViewCell.identifier)
        entPostTableView.delegate = self
        entPostTableView.dataSource = self
        super.viewDidLoad()
        
        EntertainmentAPI.getFeedPosts { result in 
            DispatchQueue.main.async {      // Ensure UI updates on main queue
                switch result {
                    case .error(let error):
                        print("There was an error: \(error)")
                    case .success(let data):
                        self.data = data
                        self.entPostTableView.reloadData
                }
            }
        }
    }
   
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let customCell1 = tableView.dequeueReusableCell(withIdentifier: EntertainmentViewrTableViewCell.identifier, for: indexPath) as! EntertainmentViewrTableViewCell
        let post = data[indexPath.row)
        customCell1.profileDisplayName.text = data[indexPath.row].postDisplayName
        customCell1.configure(with: post.postDisplayName, PostImage: post.imageURLString, PostDescription: post.postDescription)
        return customCell1   
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data.count
    }
    
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
}

public class EntertainmentAPI {
    static func getFeedPosts(completion: @escaping ((Result<[EntertainmentPageData],Error>) -> Void) ) {
        guard let apiURL = URL(string: "https://api.quickques.com/....") else {
        return
    }
    
    let task = URLSession.shared.dataTask(with: apiURL) { data, apiResponse, error in

            if let error = error {
                completion(.failure(error))
                return
            }
            
            guard let data = data else { 
                /// TODO - Invoke the completion handler with a .failure case
                return 
            }
            
            do {
                let entPostData = try JSONDecoder().decode([EntertainmentPageData].self, from: Data)
                completion(.success(entPostData))
            }
            catch {
                completion(.failure(error))
            }
            
        }.resume()
    }
}
  • Related