UITableView won't display information from array - swift

So I'm trying to create a tableview and a cell won't show up. Other than not appending anything to the recipes array, is there anything blatantly wrong with my code?
If this means anything, when I try to link the tableview to my code, it doesn't give me the opportunity to create an outlet. Github link here
I'm New to iOS programming so this might be a dumb question, sorry if that's the case.
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var recipes : [Recipe] = []
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
let recipe = recipes[indexPath.row]
cell.textLabel?.text = recipe.title!
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return recipes.count
}
func createRecipe() -> [Recipe] {
let recipe1 = Recipe()
recipe1.title = "Test"
recipe1.instructions = "testing"
recipe1.time = "testing"
let recipe2 = Recipe()
recipe2.title = "Test2"
recipe2.instructions = "testing"
recipe2.time = "testing"
return [recipe1, recipe2]
}
}
Thanks.

You need to assign Recipe Class Array in viewDidLoad and In cellForAt assign UITableviewCell
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
recipes = createRecipe()
tableView.reloadData()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = let cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
let recipe = recipes[indexPath.row]
cell.textLabel?.text = recipe.title!
return cell
}

Where are you calling createRecipe()? Where are you adding recipes to your recipes array? I think what you meant was to write recipes = createRecipe() in your viewDidLoad. Additionally to be sure your tableView is loaded with the latest data, add tableView.reloadData()
as well.
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
recipes = createRecipe()
tableView.reloadData()
}
Otherwise your recipe is would be just an empty array which translates to 0 rows...

Actually the problem is within your storyboard. Your controller is not ViewController is a basic UIViewController. So you need to change the type from UIViewController to ViewController and link your tableView after. That's why I didn't work when you were trying to link it the first time. I uploaded an image to be clear.

I wasn't saving to coreData as the Recipe class was created in coreData, and I wasn't saving anything from the createRecipe function.
Here's the fixes
New Function:
func getRecipes() {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
do {
recipes = try context.fetch(Recipe.fetchRequest()) as! [Recipe]
print(recipes)
} catch {
print("ERROR")
}
}
Revised createRecipe()
func createRecipe() -> [Recipe] {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let recipe3 = Recipe(context: context)
recipe3.title = "test3"
recipe3.instructions = "testing"
recipe3.time = "testing"
(UIApplication.shared.delegate as! AppDelegate).saveContext()
navigationController!.popViewController(animated: true)
return [recipe3]
}
And the viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
recipes = createRecipe()
getRecipes()
}

Related

Table View is now shown in simülatör swift/xcode

hello i am new to learning swift. I want to save data in database and show it in tableview. But even though I do everything, the tableview does not appear in the simulator. white screen appears. Any idea about the reason? I looked at the previous questions but couldn't find an answer.
import UIKit
import CoreData
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
#IBOutlet weak var tableView: UITableView!
//tanımlamalar
var nameArray = [String]()
var idArray = [UUID]()
override func viewDidLoad() {
super.viewDidLoad()
//tableview gösterme
tableView.delegate = self
tableView.dataSource = self
//add butonu ekleme
navigationController?.navigationBar.topItem?.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.add, target: self, action: #selector(addButtonClicked))
}
//verileri getirme
func getData() {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
//getirme
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName : "Paintings")
fetchRequest.returnsObjectsAsFaults = false
do{
let results = try context.fetch(fetchRequest)
for result in results as! [NSManagedObject] {
if let name = result.value(forKey: "name") as? String{
self.nameArray.append(name)
}
if let id = result.value(forKey: "id") as? UUID{
self.idArray.append(id)
}
//yeni veri eklenirse tableviewı reload et
self.tableView.reloadData()
}
}catch{
print("error")
}
}
//add butonuna tıklanırsa ne olacak
#objc func addButtonClicked() {
performSegue(withIdentifier: "DetailsVC", sender: nil)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return nameArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
var content = cell.defaultContentConfiguration()
content.text = nameArray[indexPath.row]
cell.contentConfiguration = content
return cell
}
}

why is storyboard UITableView not showing

I am a novice to swift. This is my first assignment for UI development. I have done the exercise perfectly and the tableView showed up as expected. The code is as below:
import UIKit
class ViewController: UIViewController {
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
tableView.delegate = self
tableView.dataSource = self
}
}
extension ViewController: UITableViewDelegate{
}
extension ViewController: UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "gameScoreCell", for: indexPath)
cell.textLabel?.text = "hello world"
cell.detailTextLabel?.text = "score"
return cell
}
}
However, when I followed the same step and tried to integrate it with my project (with a navigation controller), the table view does not show up. Did I miss anything?
import UIKit
class HightScoreVC: UIViewController {
#IBOutlet var rankingTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
rankingTable.delegate = self
rankingTable.dataSource = self
}
}
extension HightScoreVC: UITableViewDelegate{
}
extension HightScoreVC: UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "gameScoreCell", for: indexPath)
cell.textLabel?.text = "hello world"
cell.detailTextLabel?.text = "123"
return cell
}
}
I think you must register your cell in ViewDidLoad():
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
rankingTable.delegate = self
rankingTable.dataSource = self
rankingTable.register(UITableViewCell.self, forCellReuseIdentifier: "gameScoreCell")
}
Points to keep in mind while working with tableview in swift.
Make sure constriants of tableview are given properly.
You have connected the class to the view controller in the identity inspector.
Provide delegate and datasource in viewDidLoad() itself rather than storyboard for better practice.
If you are creating xib for a cell, make sure you have registered the cell for your tableview, or if you are providing prototype cell, make sure you provide dequeueReusableCell() method and initialize your cell for some specific class.
Simple example for a tableview with some prototype cell
import UIKit
class UsersListViewController: UIViewController, Storyboarded {
//MARK: - Variables
var coordinator: AuthenticationCoordinator?
var usersList: UsersList?
//MARK: - Outlets
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var progressBar: UIActivityIndicatorView!
#IBOutlet weak var btnAddUser: UIButton!
//MARK: - UIViewController
override func viewDidLoad() {
super.viewDidLoad()
initializeView()
getUsersList()
}
//MARK: - Actions
#IBAction func addUserAction(_ sender: UIButton) {
coordinator?.presentAddUser()
}
//MARK: - File private functions
fileprivate func initializeView() {
self.title = "Users list"
progressBar.startAnimating()
btnAddUser.layer.masksToBounds = true
btnAddUser.layer.cornerRadius = btnAddUser.frame.height / 2
tableView.delegate = self
tableView.dataSource = self
}
fileprivate func getUsersList() {
guard let url = URL(string: ApiUrl.delayResponseURL.rawValue) else { return }
var request = URLRequest(url: url)
request.httpMethod = "GET"
URLSession.shared.dataTask(with: request) { data, response, error in
guard error == nil else { return }
guard let data = data else { return }
guard let response = response as? HTTPURLResponse, (200 ..< 299) ~= response.statusCode else { return }
do {
guard let jsonObject = try JSONSerialization.jsonObject(with: data) as? [String: Any] else { return }
guard let prettyJsonData = try? JSONSerialization.data(withJSONObject: jsonObject, options: .prettyPrinted) else { return }
guard let responseData = try? JSONDecoder().decode(UsersList.self, from: prettyJsonData) else { return }
self.usersList = responseData
DispatchQueue.main.async {
self.progressBar.stopAnimating()
self.progressBar.alpha = 0
self.tableView.reloadData()
}
} catch {
return
}
}.resume()
}
}//End of class
//MARK: - UITableViewDelegate
extension UsersListViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let index = usersList?.data[indexPath.row].userID {
coordinator?.startSingleUserVC(index)
tableView.deselectRow(at: indexPath, animated: true)
}
}
}//End of extension
//MARK: - UITableViewDataSource
extension UsersListViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "singleUserCell") as? SingleUserTableViewCell {
if let url = URL(string: usersList?.data[indexPath.row].avatar ?? "") {
DispatchQueue.global().async {
guard let data = try? Data(contentsOf: url) else { return }
val currentUser = self.usersList?.data[indexPath.row]
DispatchQueue.main.async {
cell.initCell(data, currentUser.firstName, currentUser.email)
}
}
}
return cell
}
return UITableViewCell()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return usersList?.data.count ?? 1
}
}//End of extension

Variable not updating inside the view

For some reason, the variable Tags isnt being updated. When SelectedSauce is ran, it should run the function and then update the variable. But it's not being updated once it leaves the function. Im not sure what is wrong with this. When I change views, I pass a variable to selectedsauce from the previous view to here. im not sure if it helps or changes anything but I am using the Realm Database
class InfoUITableViewController: UITableViewController {
var SelectedSauce: Sauce? {
didSet {
print("1st")
AcquireData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
print("3rd")
print("Loaded")
tableView.register(UINib(nibName: "DetailsTableViewCell", bundle: nil), forCellReuseIdentifier: "Super")
tableView.dataSource = self
//Returns nill even though i changed the variable in acquiredata
print(Tags)
}
let realm = try! Realm()
var Tags: List<NiceTags>?
//MARK: - Data Manipulation
func AcquireData() {
print("2nd")
if let Sauce = SelectedSauce {
Tags = Sauce.tags
// print(Tags)
}
self.Tags = self.SelectedSauce?.tags
print(self.Tags)
tableView.reloadData()
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("4th")
let cell = tableView.dequeueReusableCell(withIdentifier: "Super", for: indexPath) as! DetailsTableViewCell
//This isn't running, and just uses the default text inside the label
if let TheTags = Tags?[indexPath.row] {
cell.Inflabel.text = TheTags.tags
}
return cell
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of row
print("5th")
//Returns 7 because tags is still nill
return Tags?.count ?? 7
}
}
Set SelectedSauce from tabbar like this
override func viewDidLoad() {
super.viewDidLoad()
swipeAnimatedTransitioning?.animationType = SwipeAnimationType.sideBySide
// isCyclingEnabled = true
// Do any additional setup after loading the view.
print("order")
let first_vc = self.viewControllers?.first as! DetailViewController
let last_vc = self.viewControllers?.last as! InfoUITableViewController
first_vc.SelectedSauce = SelectedSauce
last_vc.SelectedSauce = SelectedSauce
}

I want to display data from CoreData into a tableview

I want to display data from CoreData into a tableview, im working on favoris, im adding my events on favoris and i want to display it inside a tableview, there is my code :
var lists : [NSManagedObject] = [] {
didSet {
favorisEventTableView.reloadData()
}
}
#IBOutlet weak var favorisEventTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
favorisEventTableView.dataSource = self
favorisEventTableView.delegate = self
loadFavoris()
// Do any additional setup after loading the view.
}
override func viewWillAppear(_ animated: Bool) {
favorisEventTableView.reloadData()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return lists.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = favorisEventTableView.dequeueReusableCell(withIdentifier: "FavorisCell")
let contentView = cell?.viewWithTag(0)
let eventId = contentView?.viewWithTag(4) as! UILabel
let item = lists[indexPath.row]
eventId.text = String((item.value(forKey: "id_event") as! Int))
return cell!
}
func loadFavoris() {
let appDelegate = UIApplication.shared.delegate as? AppDelegate
let coreContext = appDelegate?.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Favoris")
do {
lists = try coreContext!.fetch(fetchRequest)
print(lists)
} catch let error as NSError {
print(error.userInfo)
}
}
But it's not displaying anything, maybe the problem on the add function ? im sure it works cause i get "saved" on the console, any help please?
PS: entity "Favoris" has only one attribute "id_event" which is an integer
You need to add loadFavoris inside viewDidLoad not cellForRowAt
override func viewDidLoad() {
super.viewDidLoad()
favorisEventTableView.dataSource = self
favorisEventTableView.delegate = self
loadFavoris()
}
You need to reload your table view every change on your list. you can do it like that
var lists : [NSManagedObject] = [] {
didSet {
tableView.reloadData()
}
}
Don't forget assign the delegate and dataSource protocols of tableView and fetch the data in viewDidLoad() function
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
loadFavoris()
}

TableViewCell.xib doesn't appear on tableview

Here is my code, it is supposed to display the users inside firebase database in customs tableviewcell.xib but when launching the app the tableview stays empty, I really don't know what's wrong in the code or what's missing, I think it is a really simple mistake but I can't figure it out.
Thanks in advance for those who will answer.
import UIKit
import Firebase
class UsersTableView: UIViewController, UITableViewDelegate, UITableViewDataSource {
// Outlets.
#IBOutlet weak var tableview: UITableView!
// Var.
var user = [User]()
override func viewDidLoad() {
super.viewDidLoad()
retrieveUsers()
// Do any additional setup after loading the view.
}
func retrieveUsers() {
let ref = Database.database().reference()
ref.child("users").queryOrderedByKey().observeSingleEvent(of: .value, with: { DataSnapshot in
let users = DataSnapshot.value as! [String: AnyObject]
self.user.removeAll()
for (_, value) in users{
//let uid = Auth.auth().currentUser!.uid
if let uid = value["userID"] as? String{
if uid != Auth.auth().currentUser!.uid {
let userToShow = User()
if let fullName = value["username"] as? String , let imagePath = value["photoURL"] as? String {
userToShow.username = fullName
userToShow.imagePath = imagePath
userToShow.userID = uid
self.user.append(userToShow)
}
}
}
}
self.tableview.reloadData()
})
ref.removeAllObservers()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableview.dequeueReusableCell(withIdentifier: "UserCell", for: indexPath) as! UserTableViewCell
cell.nameLabel.text = self.user[indexPath.row].username
cell.userID = self.user[indexPath.row].userID
cell.userImage.downloadImage(from: self.user[indexPath.row].imagePath!)
//checkFollowing(indexPath: indexPath)
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return user.count ?? 0
}
}
extension UIImageView{
func downloadImage(from imgURL: String!) {
let url = URLRequest(url: URL(string: imgURL)!)
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
if error != nil{
print(error)
return
}
DispatchQueue.main.async {
self.image = UIImage(data: data!)
}
}
task.resume()
}
}
If you have not set delegate and datasource for your tableView in your storyboard do it programmatically:
override func viewDidLoad() {
super.viewDidLoad()
//Add these 2 lines, might be missed.
self.tableview.delegate = self
self.tableview.dataSource = self
retrieveUsers()
}
CheckList:
Set tableView Delegate and Datasource
self.tableview.delegate = self
self.tableview.dataSource = self
Registered custom tableViewCell?
let cellNIb = UINib.init(nibName:"Identifier_Name", bundle: nil)
register(cellNIb, forCellReuseIdentifier: identifier)
check the return count of func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
​
There are two things that you forgot:
Set dataSource of your table view as your controller. If you don't do it, your tableView won't want any data. So set it in controller's viewDidLoad
tableview.dataSource = self
If you created custom xib for your cell, don't forget to register your custom cell for table view (also you can do it in viewDidLoad)
tableview.register(UINib(nibName: "UserCardTableViewCell", bundle: nil), forCellReuseIdentifier: "UserCell")
If you need UITableViewDelegate methods like didSelectRowAt too, don't forget to set delegate of your table view as your controller too
tableview.delegate = self