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
}
Related
I am trying to retrieve information stored in a Firebase Database, but my tableview is not displaying the information. I have tried using print functions to see if the data is being retrieved, and it shows that this is the case, but the tableview shows up as blank when I run the simulator.
I am using Xcode 11 and every tutorial that I have looked at is not working for some reason.
Here is my code:
import UIKit
import Firebase
import FirebaseDatabase
import SwiftKeychainWrapper
import FirebaseAuth
class FeedVC: UITableViewController {
var currentUserImageUrl: String!
var posts = [postStruct]()
var selectedPost: Post!
override func viewDidLoad() {
super.viewDidLoad()
getUsersData()
getPosts()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func getUsersData(){
guard let userID = Auth.auth().currentUser?.uid else { return }
Database.database().reference().child("users").child(userID).observeSingleEvent(of: .value) { (snapshot) in
if let postDict = snapshot.value as? [String : AnyObject] {
self.tableView.reloadData()
}
}
}
struct postStruct {
let firstName : String!
let lastName : String!
}
func getPosts() {
let databaseRef = Database.database().reference()
databaseRef.child("profiles").queryOrderedByKey().observeSingleEvent(of: .childAdded, with: {
snapshot in
let firstName = (snapshot.value as? NSDictionary)!["profileForename"] as? String
let lastName = (snapshot.value as? NSDictionary
)!["profileSurname"] as? String
print(firstName)
self.posts.append(postStruct(firstName: firstName, lastName: lastName))
print(self.posts)
DispatchQueue.main.async {
self.tableView.reloadData()
}
})
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell") as? PostCell else { return UITableViewCell() }
let nameLabel = cell.viewWithTag(1) as! UILabel
nameLabel.text = posts[indexPath.row].firstName
return cell
}
}
Any help would be much appreciated!
Update: Since PostCell is created in the storyboard within the table view it's registered and dequeued successfully. So the issue is being narrowed down to the label with tag 1. Try creating an #IBOutlet for the label and use that to set the text of UILabel.
Then in cellForRowAt:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell") as? PostCell else { return UITableViewCell() }
cell.firstNameLabel.text = posts[indexPath.row].firstName
return cell
}
Previous: You seem to have forgotten to register the PostCell.
override func viewDidLoad() {
super.viewDidLoad()
//...
tableView.register(PostCell.self, forCellReuseIdentifier: "PostCell")
}
Note: If you've created PostCell in Xib use nib registry method.
Update: If you want to register with Nib method use:
tableView.register(UINib(nibName: <#T##String#>, bundle: nil), forCellReuseIdentifier: "PostCell") // provide the xib file name at the placeholder
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()
}
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
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()
}
The cell labels are blank in the master view of a default Master Detail View when starting in landscape orientation of an iPad 2 simulation. If I reload the master view in its controller's viewWillAppear function, everything is as it should be only after turning into portrait and back into landscape. I can't figure out what I am missing despite several hours of searching for help and trying to tableView.reloadData() in various places.
This is a UIDocument app and I have not yet implemented iCloud, although I have the code ready to go. Thus far, it just needs to fetch the local document URLs, file names, and display names (?) into an array from which the master view cell labels are created.
Here is most of the MasterViewController class:
class MasterViewController: UITableViewController, DetailViewControllerDelegate {
private var detailViewController: DetailViewController? = nil
// var objects = [AnyObject]()
internal lazy var notesController = NotesController()
internal override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
print("viewDidLoad")
// determine preferred storage location for documents
notesController.documentsInCloud = false
// discover documents
notesController.discoverDocuments()
// tableView.reloadData()
navigationItem.leftBarButtonItem = editButtonItem()
if let split = splitViewController {
let controllers = split.viewControllers
detailViewController =
(controllers[controllers.count-1] as! UINavigationController
).topViewController as? DetailViewController
detailViewController!.delegate = self
}
}
internal override func viewWillAppear(animated: Bool) {
print("viewWillAppear")
clearsSelectionOnViewWillAppear = splitViewController!.collapsed
super.viewWillAppear(animated)
tableView.reloadData()
}
// MARK: - Segues
internal override func prepareForSegue(segue: UIStoryboardSegue,
sender: AnyObject?) {
print("prepareForSegue")
if segue.identifier == "showDetail" {
if let indexPath = tableView.indexPathForSelectedRow {
let controller =
(segue.destinationViewController as! UINavigationController
).topViewController as! DetailViewController
let URL = notesController.notes.array[indexPath.row].URL
controller.delegate = self
controller.detailItem = Note(fileURL: URL)
controller.selectedItemIndex = indexPath.row
controller.navigationItem.leftBarButtonItem =
splitViewController?.displayModeButtonItem()
controller.navigationItem.leftItemsSupplementBackButton = true
splitViewController?.toggleMasterView()
} else {
let controller =
(segue.destinationViewController as! UINavigationController
).topViewController as! DetailViewController
controller.delegate = self
controller.configureView()
controller.navigationItem.leftBarButtonItem =
splitViewController?.displayModeButtonItem()
controller.navigationItem.leftItemsSupplementBackButton = true
}
}
}
// MARK: - Table View
internal override func numberOfSectionsInTableView(tableView: UITableView)
-> Int {
return 1
}
internal override func tableView(tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
return notesController.notes.array.count
}
internal override func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath)
-> UITableViewCell {
print("cellForRowAtIndexPath")
let cell =
tableView.dequeueReusableCellWithIdentifier(
"Cell",
forIndexPath: indexPath)
let fileRepresentation = notesController.notes.array[indexPath.row]
if let title = fileRepresentation.displayName {
cell.textLabel?.text = title
} else {
cell.textLabel?.text = fileRepresentation.fileName
}
return cell
}
internal override func tableView(tableView: UITableView,
canEditRowAtIndexPath indexPath: NSIndexPath)
-> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
internal override func tableView(
tableView: UITableView,
commitEditingStyle
editingStyle: UITableViewCellEditingStyle,
forRowAtIndexPath indexPath: NSIndexPath) {
print("commitEditingStyle")
if editingStyle == .Delete {
let fileManager = NSFileManager.defaultManager()
let fileRepresentation = notesController.notes.array[indexPath.row]
let URL = fileRepresentation.URL
do {
try fileManager.removeItemAtURL(URL);
notesController.notes.delete(fileRepresentation);
tableView.deleteRowsAtIndexPaths([indexPath],
withRowAnimation: .Fade);
performSegueWithIdentifier("showDetail", sender: self)
} catch let error as NSError {
print(error.localizedDescription)
}
} // else if editingStyle == .Insert {
// Create a new instance of the appropriate class, insert it into
// the array, and add a new row to the table view.
// }
}
// MARK: - Delegate Functions
internal func reloadMasterViewData(sender: DetailViewController) {
tableView.reloadData()
}
}
For those who, like me, are new to the default Xcode Master-Detail view setup, yes, the Master view does start in landscape orientation populated with whatever labels it is set up to display. My problem was that the array I am using to populate the labels is constructed asynchronously from the views, and that array wasn't ready when the view loaded. I fixed this by setting up an NSNotification that told my master view when the array was finished discovering my UIDocuments. Andrew Bancroft's blog (https://www.andrewcbancroft.com/2014/10/08/fundamentals-of-nsnotificationcenter-in-swift/) was very helpful in that regard.