I have a UITableView and I need to populate with cells using data from some JSON that I get online. I have successfully acquired and parsed the data. The issue lies in the cells not being created with the proper data because they are created before the JSON Finishes loading and therefore cannot be displayed with the data. I know that you can easily use tableView.reloadData() and I run into another issue. I need to get the data downloaded before I even call any of the tableView methods.
The reason for this is because I want to return the number of cells based on how many cells are in the JSON. so something like jsoncells.count
This is my code so far: I had versions that kinda worked but they're gone since I've been tinkering with the code a little bit.
import UIKit
class TimelineViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var backgroundImageView: UIImageView!
var timelineCellDataArray = [[String:String]]()
override func viewDidLoad() {
super.viewDidLoad()
setupBackground(backgroundImage: #imageLiteral(resourceName: "Placeholder 1.jpeg"))
}
func setupBackground(backgroundImage: UIImage) {
backgroundImageView.image = backgroundImage
// Background Image Blur Effect:
let backgroundImageBlurEffect = UIBlurEffect(style: .light)
let backgroundImageBlurEffectView = UIVisualEffectView(effect: backgroundImageBlurEffect)
backgroundImageBlurEffectView.frame = backgroundImageView.frame
backgroundImageView.addSubview(backgroundImageBlurEffectView)
}
// Change View Controller To Profle View Controller
func setViewToProfileViewController() {
print("H")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "ProfileViewController") as! ProfileViewController
self.navigationController?.pushViewController(vc, animated: true)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 4
}
var isLoad = true
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "TimelineCell", for: indexPath) as! TimelineCell
// Json Parsing For Cell Populating
let urlString = "https://www.jasonbase.com/things/QRkQ.json"
let url = URL(string: urlString)
URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error != nil {
} else {
do {
let parsedData = try JSONSerialization.jsonObject(with: data!) as! [String:[[String:String]]]
self.timelineCellDataArray = parsedData["timelineCell"]!
DispatchQueue.main.async {
print("we")
switch self.timelineCellDataArray[indexPath.row]["cellType"] {
case "1"?:
cell = cell.createPostCell(cellToUse: cell)
case "2"?:
cell = cell.createPartyCell(cellToUse: cell)
case"3"?:
cell = cell.createFriendRequestCell(cellToUse: cell)
default:
break
}
tableView.reloadData()
self.isLoad = false
}
} catch let error as NSError {
print(error)
}
}
}.resume()
print("WD")
return cell
}
}
Here is my JSON https://www.jasonbase.com/things/QRkQ.json
cellForRowAtis a terrible idea. You need to load your data fromviewDidLoador some other appropriate place where the data is only loaded once, not for every cell.createPostCellshouldn't do all these things at once: be a non-static function for a cell, take in a cell as a parameter, and return a new cell. It is better coding practice to havecreatePostCelljust be a non-static function that takes in the data that you use to populate the instance of that cell.