People tell me how to get out of my position and do so that when a new event is added it becomes the beginning, not the end.I will be very grateful for the help.
I have three arrays and I had to sort them out by the parent cells, and in this line I very much played func tableView (_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
import UIKit
import Parse
class PrognozSegmentViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
var soccerString = [Soccer]()
var basketString = [Basketball]()
var tennisString = [Tennis]()
var refresh : UIRefreshControl!
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var segmentControl: UISegmentedControl!
#IBAction func btnSegment(_ sender: Any) {
tableView.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
refresh = UIRefreshControl()
refresh.attributedTitle = NSAttributedString(string: "Потяните вниз чтоб обновить ресурс")
refresh.tintColor = UIColor.green
refresh.addTarget(self, action: #selector(PrognozSegmentViewController.refreshing), for: UIControlEvents.valueChanged)
tableView.addSubview(refresh)
setupSeg()
tableView.tableFooterView = UIView()
tableView.estimatedRowHeight = 88
tableView.rowHeight = UITableViewAutomaticDimension
tableView.separatorStyle = UITableViewCellSeparatorStyle.none
tableView.register(UINib(nibName:"TableViewCell",bundle:nil), forCellReuseIdentifier: "sportCell")
loadObjects1()
loadObjects2()
loadObjects3()
}
func setupSeg() {
let attributes = [ NSAttributedStringKey.foregroundColor : UIColor.yellow,
NSAttributedStringKey.font : UIFont.systemFont(ofSize: 10, weight: UIFont.Weight.bold)];
let attributesSelected = [ NSAttributedStringKey.foregroundColor : UIColor.black,
NSAttributedStringKey.font : UIFont.systemFont(ofSize: 12, weight: UIFont.Weight.bold)];
segmentControl.setTitleTextAttributes(attributes, for: UIControlState.normal)
segmentControl.setTitleTextAttributes(attributesSelected, for: UIControlState.selected)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var returnSport = 0
switch (segmentControl.selectedSegmentIndex) {
case 0 :
returnSport = soccerString.count
break
case 1 :
returnSport = basketString.count
break
case 2 :
returnSport = tennisString.count
break
default :
break
}
return returnSport
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let sportCell = tableView.dequeueReusableCell(withIdentifier: "sportCell", for: indexPath) as! TableViewCell
switch (segmentControl.selectedSegmentIndex) {
case 0 :
let soccer = soccerString[indexPath.row]
sportCell.matchLabel.text = soccer.matchS
soccerString[indexPath.row].imagePrS.getDataInBackground {(data, error) in
sportCell.imageMatch.image = error == nil ? UIImage(data: data!) : nil
}
break
case 1 :
let basket = basketString[indexPath.row]
sportCell.matchLabel.text = basket.matchB
basketString[indexPath.row].imagePrB.getDataInBackground {(data, error) in
sportCell.imageMatch.image = error == nil ? UIImage(data: data!) : nil
}
break
case 2:
sportCell.matchLabel.text = tennisString[indexPath.row].matchT
tennisString[indexPath.row].imagePrT.getDataInBackground {(data, error) in
sportCell.imageMatch.image = error == nil ? UIImage(data: data!) : nil
}
break
default:
break
}
sportCell.selectionStyle = UITableViewCellSelectionStyle.none
let date = Date()
let calendar = Calendar.current
let yesterday = calendar.date(byAdding: .day, value: -1, to: date)
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "EEEE, MMM:d, yyyy"
dateFormatter.dateStyle = .short
dateFormatter.timeStyle = .short
dateFormatter.locale = Locale(identifier: "ru_UA")
dateFormatter.doesRelativeDateFormatting = true
let dataFormater2 = DateFormatter()
dataFormater2.dateFormat = "EEEE, MMM:d, yyyy"
dataFormater2.dateStyle = .short
dataFormater2.timeStyle = .short
dataFormater2.locale = Locale(identifier: "ru_UA")
dataFormater2.doesRelativeDateFormatting = true
sportCell.dataSave.text! = dateFormatter.string(from: date)
sportCell.dataSave.text = dateFormatter.string(from: yesterday!)
return sportCell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func loadObjects1() {
let query = Soccer.query() as! PFQuery<Soccer>
query.findObjectsInBackground { (objects, error) in
if error == nil {
self.soccerString.removeAll()
self.soccerString = objects!
self.tableView.reloadData()
} else {
print(error!)
}
}
}
func loadObjects2() {
let query = Basketball.query() as! PFQuery<Basketball>
query.findObjectsInBackground { (objects, error) in
if error == nil {
self.basketString.removeAll()
self.basketString = objects!
self.tableView.reloadData()
} else {
print(error!)
}
}
}
func loadObjects3() {
let query = Tennis.query() as! PFQuery<Tennis>
query.findObjectsInBackground { (objects, error) in
if error == nil {
self.tennisString.removeAll()
self.tennisString = objects!
self.tableView.reloadData()
} else {
print(error!)
}
}
}
#objc func refreshing() {
loadObjects1()
loadObjects2()
loadObjects3()
tableView.reloadData()
refresh.endRefreshing()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch (segmentControl.selectedSegmentIndex) {
case 0 :
if segue.identifier == "showSoccer" {
if let indexPath = tableView.indexPathForSelectedRow {
let destationViewController = segue.destination as! DetailSoccerTableViewController
destationViewController.detailSoccer = self.soccerString[indexPath.row]
}
}
case 1 :
if segue.identifier == "showBasket" {
let dvc = segue.destination as! DetailBasketViewController
if let indexPath = tableView.indexPathForSelectedRow {
let row = Int(indexPath.row)
dvc.baskets = basketString[row]
}
}
case 2 :
let destationVC: DetailTennisViewController = segue.destination as! DetailTennisViewController
if let indexPath = self.tableView.indexPathForSelectedRow {
let row = Int(indexPath.row)
destationVC.tenises = tennisString[row]
}
self.present(destationVC, animated: true, completion: nil)
default :
break
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
switch ( segmentControl.selectedSegmentIndex) {
case 0 :
let soccer = soccerString[indexPath.row]
performSegue(withIdentifier: "showSoccer", sender: soccer)
break
case 1 :
let basket = basketString[indexPath.row]
let destinationVC = DetailBasketViewController()
destinationVC.baskets = basket
self.performSegue(withIdentifier: "showBasket", sender: self)
break
case 2 :
let tennis = tennisString[indexPath.row]
let destTenVC = DetailTennisViewController()
destTenVC.tenises = tennis
self.performSegue(withIdentifier: "showTennis", sender: self)
break
default :
break
}
}
}
If your problem is the new object becomes the last
I assume you're talking about an array and you're doing
array.append(item)
If you want to have the item at the beginning do:
array.insert(item, at: 0)
And then
tableView.reloadData()
Related
I am trying to get the inputted text from recipeName, servingsNumber, prepTime and cookTime to save to fb.
I know this is close to where I need to be. I am need some help with my save function. I need to assign the textField.text in sendToFirebase() I am able to print out the inputted text into the console and I was able to get it to save a document to FB but the entry was null. What am I missing? I feel like it is here in my code:
import UIKit
import Firebase
class AddRecipeViewController: UIViewController {
#IBOutlet weak var table: UITableView!
#IBOutlet weak var saveButton: UIBarButtonItem!
let db = Firestore.firestore()
var id = UUID().uuidString
var data = [RecipeData]()
let user = Auth.auth().currentUser?.email
var objRecipe = RecipeData.init()
override func viewDidLoad() {
super.viewDidLoad()
table.delegate = self
table.dataSource = self
navigationItem.hidesBackButton = true
let newBackButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancelPressed))
self.navigationItem.leftBarButtonItem = newBackButton
table.register(UINib(nibName: "RecipeNameCell", bundle: nil), forCellReuseIdentifier: "recipeName")
table.register(UINib(nibName: "ServingSizeTableViewCell", bundle: nil), forCellReuseIdentifier: "servings")
table.register(UINib(nibName: "PrepTimeTableViewCell", bundle: nil), forCellReuseIdentifier: "prep")
table.register(UINib(nibName: "CookTimeTableViewCell", bundle: nil), forCellReuseIdentifier: "cook")
}
func sendToFirebase() {
do {
let recipeName = objRecipe.recipeName
let servings = objRecipe.servingsNumber
let prep = objRecipe.prepTime
let cook = objRecipe.cookTime
let user = Auth.auth().currentUser?.email
let id = objRecipe.id
let data = try JSONEncoder().encode(objRecipe)
let dictionary = (try? JSONSerialization.jsonObject(with: data)) as? [String: Any] ?? [:]
db.collection("Recipe").document(objRecipe.id).setData(dictionary)
}
catch {
print(error)
}
}
#objc func cancelPressed(sender: UIBarButtonItem) {
navigationController?.popViewController(animated: true)
dismiss(animated: true, completion: nil)
}
#IBAction func savePressed(_ sender: UIBarButtonItem) {
sendToFirebase()
}
}
extension AddRecipeViewController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 4
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = table.dequeueReusableCell(withIdentifier: "recipeName", for: indexPath) as! RecipeNameCell
cell.textField.delegate = self
cell.textField.tag = indexPath.row
return cell
}
else if indexPath.row == 1 {
let cell = table.dequeueReusableCell(withIdentifier: "servings", for: indexPath) as! ServingSizeTableViewCell
cell.textField.delegate = self
cell.textField.tag = indexPath.row
return cell
}
else if indexPath.row == 2 {
let cell = table.dequeueReusableCell(withIdentifier: "prep", for: indexPath) as! PrepTimeTableViewCell
cell.textField.delegate = self
cell.textField.tag = indexPath.row
return cell
}
else if indexPath.row == 3{
let cell = table.dequeueReusableCell(withIdentifier: "cook", for: indexPath) as! CookTimeTableViewCell
cell.textField.delegate = self
cell.textField.tag = indexPath.row
return cell
}
else {
let cell = table.dequeueReusableCell(withIdentifier: "recipeName", for: indexPath) as! RecipeNameCell
return cell
}
}
}
extension AddRecipeViewController: UITextFieldDelegate {
func textFieldDidEndEditing(_ textField: UITextField) {
switch textField.tag {
case 0:
let recipeName = textField.text!
print(recipeName)
objRecipe.recipeName = textField.text!
// sendToFirebase() // Send to firebase
case 1:
let servingSize = textField.text!
print(servingSize)
objRecipe.servingsNumber = textField.text!
// sendToFirebase() // Send to firebase
case 2:
let prepTime = textField.text!
print(prepTime)
objRecipe.prepTime = textField.text!
// sendToFirebase() // Send to firebase
case 3:
let cookTime = textField.text!
print(cookTime)
objRecipe.cookTime = textField.text!
// sendToFirebase() // Send to firebase
default: break
}
}
}
struct RecipeData: Codable {
var user: String?
var recipeName: String?
var ingredientsText: String?
var directionsText: String?
var servingsNumber: String?
var prepTime: String?
var cookTime: String?
var image: String?
let id = UUID().uuidString
}
class RecipeNameCell: UITableViewCell {
#IBOutlet weak var textField: UITextField!
var id = UUID().uuidString
let db = Firestore.firestore()
var name: String?
override func awakeFromNib() {
super.awakeFromNib()
textField.placeholder = "Recipe Name..."
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
func saveData(text: String) {
if let recipeName = recipeNameTextField.text,
let addedIngredients = ingredientsTextField.text,
let directionsText = directionsTextField.text,
let servingsNum = numServingLabel.text,
let image = imageView.image,
let user = Auth.auth().currentUser?.email {
let newRecipeRef = db.collection(D.FStore.collectionName).document(id)
newRecipeRef.setData([
D.FStore.recipeTextField: recipeName,
D.FStore.ingredientsText: addedIngredients,
D.FStore.directionsText: directionsText,
D.FStore.numberServings: servingsNum,
D.FStore.userField: user,
D.FStore.id: id,
D.FStore.image: image,
]) { err in
if let err = err {
print("Error adding document: \(err)")
} else {
print("Document added with ID:\(newRecipeRef)")
}
}
}
}
import UIKit
import Firebase
class HomeScreenViewController: UIViewController {
#IBOutlet weak var table: UITableView!
#IBOutlet weak var logout: UIBarButtonItem!
#IBOutlet weak var add: UIBarButtonItem!
let db = Firestore.firestore()
var data = [RecipeData]()
var recipeNamed: String?
override func viewDidLoad() {
super.viewDidLoad()
table.delegate = self
table.dataSource = self
navigationItem.hidesBackButton = true
table.register(UINib(nibName: "RecipeCell", bundle: nil), forCellReuseIdentifier: "cell")
}
func loadRecipeNames() {
db.collection("Recipe")
.addSnapshotListener { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in querySnapshot!.documents {
let data = document.data()
if let user = data["User"] as? String,
let recipeNameLabels = data["Recipe Name"] as? String,
let prep = data["Prep Time"] as? String,
let cook = data["Cook Time"] as? String,
let servings = data["Servings"] as? String
{
let newRecipe = RecipeData(user: user, recipeName: recipeNameLabels, servingsNumber: servings, prepTime: prep, cookTime: cook)
self.data.append(newRecipe)
}
DispatchQueue.main.async {
self.table.reloadData()
}
}
}
}
}
#IBAction func logoutPress(_ sender: UIBarButtonItem) {
do {
try Auth.auth().signOut()
navigationController?.popToRootViewController(animated: true)
} catch let signOutError as NSError {
print("Error signing out: %#", signOutError)
}
}
#IBAction func addRecipePressed(_ sender: UIBarButtonItem) {
performSegue(withIdentifier: "add", sender: self)
}
}
extension HomeScreenViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let data = data[indexPath.row]
let cell = table.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! RecipeCell
cell.recipeNameLabel.text = data.recipeName
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "DetailSegue", sender: self)
}
}
You need to fire the sendToFirebase() function:
extension AddRecipeViewController: UITextFieldDelegate {
func textFieldDidEndEditing(_ textField: UITextField) {
switch textField.tag {
case 0:
let recipeName = textField.text!
print(recipeName)
objRecipe.recipeName = textField.text!
sendToFirebase() // Send to firebase
case 1:
let servingSize = textField.text!
print(servingSize)
objRecipe.servingsNumber = textField.text!
sendToFirebase()
case 2:
let prepTime = textField.text!
print(prepTime)
objRecipe.prepTime = textField.text!
sendToFirebase()
case 3:
let cookTime = textField.text!
print(cookTime)
objRecipe.cookTime = textField.text!
sendToFirebase()
default: break
}
}
}
sendToFirebase() function:
func sendToFirebase() {
let recipeName = objRecipe.recipeName
let servings = objRecipe.servingsNumber
let prep = objRecipe.prepTime
let cook = objRecipe.cookTime
let user = Auth.auth().currentUser?.email
let newRecipeRef = db.collection("Recipe").document(objRecipe.id)
newRecipeRef.setData([
"Recipe Name" : recipeName ?? "Empty",
"Serving #" : servings ?? "Empty",
"Prep Time" : prep ?? "Empty",
"Cook Time" : cook ?? "Empty",
"User" : user ?? "No email provided",
])
{ err in
if let err = err {
print("Error adding document: \(err)")
} else {
print("Document added with ID:\(newRecipeRef)")
}
}
}
You get one thing figured out and something else comes along and that's why I love this stuff.
My workout app uses realm for data persistence and when I modify some of the data elements of the file, it crashes when I reload the tableView. Here is a layout of the tableview in WorkoutViewController.
I select an item to edit it's three properties (Name, Date and average time). When selecting Edit the following view controller is presented. This is WorkoutAlertViewController.
Here is the relevant code:
class WorkoutViewController: UIViewController {
let realm = try! Realm()
var workoutItems: Results<Workout>?
var passedWorkout = Workout()
#IBOutlet weak var tableView: UITableView!
func editWorkout(workout: Workout, name: String, time: String, date: Date) {
do {
try self.realm.write {
passedWorkout = workout
print("passedWorkout \(workout)")
print("changes to be made \(name), \(time), \(date)")
passedWorkout.name = name
passedWorkout.time = time
passedWorkout.dateCreated = date
print("workout changed \(passedWorkout)")
}
} catch {
print("Error editing workout \(error)")
}
// loadWorkout()
}
func loadWorkout() {
workoutItems = realm.objects(Workout.self).sorted(byKeyPath: "name", ascending: false)
print("workoutItems \(String(describing: workoutItems))")
tableView.reloadData()
}
}
extension WorkoutViewController: PassNewWorkout {
func didTapAdd(name: String, time: String, date: Date) {
workoutName = name
averageTime = time
creationDate = date
let newWorkout = Workout()
newWorkout.name = workoutName
newWorkout.dateCreated = creationDate
newWorkout.time = averageTime
saveWorkout(workout: newWorkout)
}
}
extension WorkoutViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return workoutItems?.count ?? 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! WorkoutCell
if let workout = workoutItems?[indexPath.row] {
cell.workoutLabel.text = workout.name
cell.dateLabel.text = String("Created: \(functions.convertTime(timeToConvert: workout.dateCreated!))")
cell.timeLabel.text = String("Avg Time: \(workout.time)")
} else {
cell.textLabel?.text = "No Workouts Added"
}
return cell
}
}
extension WorkoutViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "workoutListSegue", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "workoutListSegue" {
if let destinationVC = segue.destination as? WorkoutListViewController, let indexPath = tableView.indexPathForSelectedRow {
if let workout = workoutItems?[indexPath.row] {
destinationVC.selectedWorkout = workout
destinationVC.workoutName = workout.name
}
}
}
}
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let deleteAction = UIContextualAction(style: .destructive, title: "Delete") { (action, view, actionPerformed) in
if let _ = tableView.cellForRow(at: indexPath){
self.passedWorkout = self.workoutItems![indexPath.row]
self.deleteWorkout(workout: self.passedWorkout)
}
tableView.reloadData()
}
deleteAction.backgroundColor = .red
let editAction = UIContextualAction(style: .normal, title: "Edit") { (action, view, actionPerformed) in
if let _ = tableView.cellForRow(at: indexPath){
let alertVC = self.storyboard!.instantiateViewController(identifier: "WorkoutVC") as! WorkoutAlertViewController
self.passedWorkout = self.workoutItems![indexPath.row]
print("editAction \(self.passedWorkout)")
alertVC.didTapEdit(workout: self.passedWorkout)
self.present(alertVC, animated: true, completion: nil)
}
}
editAction.backgroundColor = .gray
return UISwipeActionsConfiguration(actions: [deleteAction, editAction])
}
}
The app crashes on loadWorkout() with:
Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file /Users/kevin/Desktop/FitTrax/FitTrax/Controller/Fitness/WorkoutViewController.swift, line 88
Line 88 is tableView.reloadData()
Here is the WorkoutAlertViewController file.
protocol PassNewWorkout {
func didTapAdd(name: String, time: String, date: Date)
}
class WorkoutAlertViewController: UIViewController {
var workoutName = String()
var averageTime = String()
var creationDate = Date()
var receivedWorkout = Workout()
#IBAction func addButtonPressed(_ sender: UIButton) {
dismiss(animated: true, completion: nil)
if workoutName == "" {
workoutName = workoutTextField.text!
creationDate = datePicker.date
averageTime = timeTextField.text!
alertDelegate.didTapAdd(name: workoutName, time: averageTime, date: creationDate)
} else {
workoutName = workoutTextField.text!
creationDate = datePicker.date
averageTime = timeTextField.text!
let workoutVC = storyboard!.instantiateViewController(withIdentifier: "Main") as! WorkoutViewController
workoutVC.editWorkout(workout: receivedWorkout, name: workoutName, time: averageTime, date: creationDate)
}
}
func didTapEdit(workout: Workout) {
workoutName = workout.name
averageTime = workout.time
creationDate = workout.dateCreated!
receivedWorkout = workout
}
}
The edit does work without the reload but does not immediately show the changes. If I go back to the Fitness Menu and back to the Workout Menu, it displays the changes then. It's something with that reload that I can't figure out.
Thank you for any suggestions.
I am using below code for the UITableView, in every cell there are two buttons configured to perform certain actions as shown in the code. Earlier it was working fine, but now As I update this code to new version of Xcode it is not working, whenever I tap on the cell or the button in the cell it doesn't perform any action, neither it shows any error, but it just darkens the half of the cell with grey colour?
Xcode earlier was 10 and now 11, swift 5 version same in both cases
There is one fixed cell at the top and then there is list of cells as per the number of documents in the database
What could be the issue?
for information I am using Swift IOS and cloud firestore database
class HomeViewController: UITableViewController {
var posts = [Post]()
var db: Firestore!
var scores1 = [Scores]()
var postAuthorId:String = ""
var postAuthorname:String = ""
var CommentAuthorName:String = ""
var PostTitle:String = ""
var postAuthorGender:String = ""
var postAuthorEmail:String = ""
var postAuthorfullname:String = ""
var postAuthorSpinnerC:String = ""
var postContent:String = ""
var postCategory:String = ""
var postAuthorPicUrl:String = ""
var postTimeStamp:String = ""
var l11:Int = 0
var postKey:String = ""
private var documents: [DocumentSnapshot] = []
override func viewDidLoad() {
super.viewDidLoad()
db = Firestore.firestore()
tableView.dataSource = self
tableView.delegate = self
retrieveAllPosts()
getuserscores()
var AViewController: UIViewController = UIViewController()
var MyTabBarItem: UITabBarItem = UITabBarItem(title: nil, image: UIImage(named: "pencil")?.withRenderingMode(UIImage.RenderingMode.alwaysOriginal), selectedImage: UIImage(named: "pencil"))
AViewController.tabBarItem = MyTabBarItem
// Do any additional setup after loading the view.
// navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Sign Out", style: .plain, target: self, action: #selector(handleLogout))
}
func getuserscores(){
let userRef = Firestore.firestore().collection("users").document(Auth.auth().currentUser!.uid)
userRef.getDocument{(document, error) in
if let document = document, document.exists{
let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
let l1 = document.get("l1") as! Int
let l2 = document.get("l2") as! Int
let l3 = document.get("l3") as! Int
let l4 = document.get("l4") as! Int
let newScores = Scores(_l1: l1, _l2: l2, _l3: l3, _l4: l4)
self.scores1.append(newScores)
}
self.tableView.reloadData()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func retrieveAllPosts(){
let postsRef = Firestore.firestore().collection("posts").order(by: "timestamp", descending: true).limit(to: 50)
postsRef.getDocuments { (snapshot, error) in
if let error = error {
print(error.localizedDescription)
} else {
if let snapshot = snapshot {
for document in snapshot.documents {
let data = document.data()
let username = data["post_author_username"] as? String ?? ""
let postTitle = data["postTitle"] as? String ?? ""
let postcategory = data["postcategory"] as? String ?? ""
let postContent = data["postContent"] as? String ?? ""
let postAuthorProfilePicUrl = data["post_user_profile_pic_url"] as? String ?? ""
let postAuthorSpinnerC = data["post_author_spinnerC"] as? String
let newSourse = Post(_documentId: document.documentID, _username: username, _postTitle: postTitle, _postcategory: postcategory, _postContent: postContent, _postuserprofileImagUrl: postAuthorProfilePicUrl, _postAuthorSpinncerC: postAuthorSpinnerC)
self.posts.append(newSourse)
}
self.tableView.reloadData()
}
}
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
tableView.estimatedRowHeight = 200
tableView.rowHeight = UITableView.automaticDimension
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return scores1.count + posts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 && scores1.count == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: "SmileMiles") as! ScoresCellInHomeScreen
cell.set(scores: scores1[indexPath.row])
return cell
} else if posts.count > (indexPath.row - 1 ) {
let cell = tableView.dequeueReusableCell(withIdentifier: "postCell", for: indexPath) as! PostTableViewCell
cell.btnComment.tag = indexPath.row - 1
cell.btnComment.addTarget(self, action: #selector(toComments(_:)), for: .touchUpInside)
cell.favoritebutton.tag = indexPath.row - 1
cell.favoritebutton.addTarget(self, action: #selector(favupdate(_:)), for: .touchUpInside)
cell.set(post: posts[indexPath.row - 1 ])
return cell
} else {
return UITableViewCell()
}
}
#objc func favupdate(_ sender: AnyObject) {
let commentbutton = sender as! UIButton
let post = posts[commentbutton.tag]
postKey = post._documentId // or what key value it is
let userMarkRef = Firestore.firestore().collection("users").document(Auth.auth().currentUser!.uid).collection("marked_posts").document(postKey)
let postRef = Firestore.firestore().collection("posts").document(postKey)
postRef.getDocument{(document, error) in
if let document = document, document.exists{
let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
self.postAuthorId = document.get("post_author_id") as! String
self.postAuthorname = document.get("post_author_username") as! String
self.PostTitle = document.get("postTitle") as! String
self.postContent = document.get("postContent") as! String
self.postAuthorEmail = document.get("post_author_email") as! String
self.postCategory = document.get("postcategory") as! String
self.postAuthorfullname = document.get("post_author_fullname") as! String
self.postAuthorGender = document.get("post_author_gender") as! String
self.postAuthorPicUrl = document.get("post_user_profile_pic_url") as! String
// let l11:Bool = document.get("l1") as! Bool
// self.postTimeStamp = document.get("post_timeStamp") as! String
self.postAuthorSpinnerC = document.get("post_author_spinnerC") as! String
}
let postObject = [
"post_author_gender": self.postAuthorGender,
// "post_author_dateOfBirth": self.dateOfBirth,
"post_author_spinnerC": self.postAuthorSpinnerC,
"post_author_fullname": self.postAuthorfullname,
"post_author_id": self.postAuthorId,
"post_author_username": self.postAuthorname,
"post_author_email": self.postAuthorEmail,
"postTitle": self.PostTitle,
"postcategory": self.postCategory,
"postContent": self.postContent,
// "post_timestamp": FieldValue.serverTimestamp(),
"post_user_profile_pic_url":self.postAuthorPicUrl,
"post_id": self.postKey
] as [String : Any]
userMarkRef.setData(postObject, merge: true) { (err) in
if let err = err {
print(err.localizedDescription)
}
print("Successfully set new user data")
}
}
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row == 0 {
return 150
}
else{
return UITableView.automaticDimension
}
}
#objc func toComments(_ sender: AnyObject) {
let commentbutton = sender as! UIButton
let post = posts[commentbutton.tag]
postKey = post._documentId // or what key value it is
print(postKey + "hello")
performSegue(withIdentifier: "toCommentsList", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "toCommentsList"){
var vc = segue.destination as! CommentListViewController
vc.postId = postKey
}
}
}
Do this in tableview cellForRowAt function before return cell:
cell.selectionStyle = .none
return cell
this will fix the issue
I've googled and read a lot of questions and answers about this topic, however I still can't solve my problem. I have a project connected to firebase, with a tableView connected to that information. The following error pops up:
unexpectedly found nil while unwrapping an Optional value.
I've checked all my connections between UIButtons, UILabels and such, and most of all i have tried using breakpoints to locate the error. However I can't seem to get my head around a solution. Here comes code and messages from the project and the error:
#IBOutlet weak var addButton: UIBarButtonItem!
let listToUsers = "ListToUsers"
var backgroundNr = 0
var items: [GroceryItem] = []
let ref = FIRDatabase.database().reference(withPath: "grocery-items")
let usersRef = FIRDatabase.database().reference(withPath: "online")
var user: User!
var userCountBarButtonItem: UIBarButtonItem!
var counter = 1
override func viewDidLoad() {
super.viewDidLoad()
if user?.email == "tor#gmail.com" {
addButton.isEnabled = false
}
tableView.allowsMultipleSelectionDuringEditing = false
userCountBarButtonItem = UIBarButtonItem(title: "1",
style: .plain,
target: self,
action: #selector(userCountButtonDidTouch))
userCountBarButtonItem.tintColor = UIColor.white
navigationItem.leftBarButtonItem = userCountBarButtonItem
usersRef.observe(.value, with: { snapshot in
if snapshot.exists() {
self.userCountBarButtonItem?.title = snapshot.childrenCount.description
} else {
self.userCountBarButtonItem?.title = "0"
}
})
ref.queryOrdered(byChild: "completed").observe(.value, with: { snapshot in
var newItems: [GroceryItem] = []
for item in snapshot.children {
let groceryItem = GroceryItem(snapshot: item as! FIRDataSnapshot)
newItems.append(groceryItem)
}
self.items = newItems
self.tableView.reloadData()
})
FIRAuth.auth()!.addStateDidChangeListener { auth, user in
guard let user = user else { return }
self.user = User(authData: user)
let currentUserRef = self.usersRef.child(self.user!.uid)
currentUserRef.setValue(self.user!.email)
currentUserRef.onDisconnectRemoveValue()
}
}
// MARK: UITableView Delegate methods
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ItemCell", for: indexPath) as! SubjectTableViewCell
let groceryItem = items[indexPath.row]
if backgroundNr == 0 {
cell.backgroundColor = UIColor(red: 222/255, green: 164/255, blue: 50/255, alpha: 0.6)
backgroundNr += 1
} else {
cell.backgroundColor = UIColor.white
backgroundNr -= 1
}
cell.textLabel?.text = groceryItem.name
cell.detailTextLabel?.text = groceryItem.addedByUser
toggleCellCheckbox(cell, isCompleted: groceryItem.completed)
return cell
}
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
let groceryItem = items[indexPath.row]
groceryItem.ref?.removeValue()
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let cell = tableView.cellForRow(at: indexPath) else { return }
let groceryItem = items[indexPath.row]
let toggledCompletion = !groceryItem.completed
toggleCellCheckbox(cell, isCompleted: toggledCompletion)
groceryItem.ref?.updateChildValues([
"completed": toggledCompletion
])
}
func toggleCellCheckbox(_ cell: UITableViewCell, isCompleted: Bool) {
if !isCompleted {
cell.accessoryType = .none
cell.textLabel?.textColor = UIColor.black
cell.detailTextLabel?.textColor = UIColor.black
} else {
cell.accessoryType = .checkmark
cell.textLabel?.textColor = UIColor.gray
cell.detailTextLabel?.textColor = UIColor.gray
}
}
// MARK: Add Item
#IBAction func addButtonTapped(_ sender: Any) {
let alert = UIAlertController(title: "Kunskaps Område",
message: "Lägg till objekt",
preferredStyle: .alert)
let saveAction = UIAlertAction(title: "Spara",
style: .default) { _ in
// 1
guard let textField = alert.textFields?.first,
let text = textField.text else { return }
// 2
let groceryItem = GroceryItem(name: text,
addedByUser: self.user!.email,
completed: false)
// 3
let groceryItemRef = self.ref.child(text.lowercased())
// 4
groceryItemRef.setValue(groceryItem.toAnyObject())
}
let cancelAction = UIAlertAction(title: "Cancel",
style: .default)
alert.addTextField()
alert.addAction(saveAction)
alert.addAction(cancelAction)
present(alert, animated: true, completion: nil)
}
func userCountButtonDidTouch() {
performSegue(withIdentifier: listToUsers, sender: nil)
}
#IBAction func startClockTapp(_ sender: Any) {
Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(GroceryListTableViewController.updateCounter), userInfo: nil, repeats: true)
}
func updateCounter() {
counter += 1
let clock = String(counter)
print(clock)
let clockCurrent = Clock(name: clock, addedByUser: self.user!.email)
let clockCurrentRef = self.ref.child(clock.lowercased())
clockCurrentRef.setValue(clockCurrent.toAnyObject())
}
When using breakpoints to locate where the error occurs, it seems that it is located in the following function: (the first line of code in "UITable view delegate methods)
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
I don't now if I'm using the breakpoints wrong, however that's the result I get, if it helps.
The "grocery" objects struct file´s code is the following:
import Foundation
import Firebase
struct GroceryItem {
let key: String
let name: String
let addedByUser: String
let ref: FIRDatabaseReference?
var completed: Bool
init(name: String, addedByUser: String, completed: Bool, key: String = "") {
self.key = key
self.name = name
self.addedByUser = addedByUser
self.completed = completed
self.ref = nil
}
init(snapshot: FIRDataSnapshot) {
key = snapshot.key
let snapshotValue = snapshot.value as! [String: AnyObject]
name = snapshotValue["name"] as! String
addedByUser = snapshotValue["addedByUser"] as! String
completed = snapshotValue["completed"] as! Bool
ref = snapshot.ref
}
func toAnyObject() -> Any {
return [
"name": name,
"addedByUser": addedByUser,
"completed": completed
]
}
}
The database content on Firebase gets structured as following:
educationlevel-e230e
grocery-items
Fysik:, addedByUser:, completed:
The full string of the basic error message:
fatal error: unexpectedly found nil while unwrapping an Optional value
2016-12-24 01:22:54.799117 EducationLevel[1077:263810]
fatal error:
unexpectedly found nil while unwrapping an Optional value
I really can't find the answer to this problem by my self or anywhere on the web, REALLY appreciates it if I could get some help (sorry for the probably bad english, I'm from Sweden;) )
(If you need more strings from the error message or anything like that I'll immediately update this question)
Thanks!! Tor from Sweden.
I have an Instagram like feed with pictures shown one at a time in each cell. You can press on them and get directed to a commentTBV. Here is where I have all the comments underneath the post and they get counted correctly in this View.
var commentsArray = [FotoComment]()
is the array holding the comments
kommentarArray is the array i want to fill with the assignArray func so i can use it to display the amount of counts.
var kommentarArray = [FotoComment]()
[FotoComment] is my struc I use for my comments
What I want is that already in the feed the commentArray.count will show the correct number of comments.
func assignArray() {
let otherVC = CommentTableViewController()
kommentarArray = otherVC.commentsArray
print(kommentarArray.count)
}
This way I get access from my feed to the array of comments in the CommentTBVC.
My cell is:
cell.kommentarZähler.text = "Kommentare: \(kommentarArray.count)"
But it always shows 0 even though it already has 5 comments and it correctly displayed on the CommentTBV.
M complete code for MemesTableViewConbtroller (the feed)
import UIKit
import Firebase
import FirebaseAuth
import FirebaseDatabase
class MemesTableViewController: UITableViewController {
var kommentarArray = [FotoComment]()
var dataBaseRef : FIRDatabaseReference!
var storageRef : FIRStorageReference!
var posts = [PostMitBild]()
var segmentedControl : HMSegmentedControl!
override func viewDidLoad() {
super.viewDidLoad()
assignArray()
segmentedControl = HMSegmentedControl(sectionTitles: ["Top Heute", "Beliebteste", "Neue"])
segmentedControl.frame = CGRect(x: 10, y: 10, width: 300, height: 60)
segmentedControl.backgroundColor = UIColor.red
segmentedControl.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
segmentedControl.borderColor = UIColor.brown
segmentedControl.tintColor = UIColor.black
segmentedControl.selectionIndicatorColor = UIColor.gray
segmentedControl.addTarget(self, action: #selector(getter: MemesTableViewController.segmentedControl), for: UIControlEvents.valueChanged)
tableView.tableHeaderView = segmentedControl
segmentedAction()
}
func segmentedAction() {
if segmentedControl.selectedSegmentIndex == 0 {
let postRef = FIRDatabase.database().reference().child("MemesBilder")
postRef.observe(.value, with: { (snapshot) in
var newPost = [PostMitBild]()
for post in snapshot.children {
let Post = PostMitBild(snapshot: post as! FIRDataSnapshot)
newPost.insert(Post, at: 0)
}
self.posts = newPost
DispatchQueue.main.async {
self.tableView.reloadData()
}
}, withCancel: { (error) in
print(error.localizedDescription)
})
}
}
//------------------------------------------
override func viewWillAppear(_ animated: Bool) {
if FIRAuth.auth()?.currentUser == nil {
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Login")
self.present(vc, animated: true, completion: nil)
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "postCell", for: indexPath) as! PostTableViewCell
if let seconds = posts[indexPath.row].postDate {
let timestamp = NSDate(timeIntervalSince1970: seconds)
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/yyyy HH:mm"
cell.uploadDatum.text = dateFormatter.string(from: timestamp as Date)
}
cell.kommentarZähler.text = "Kommentare: \(kommentarArray.count)"
cell.usernameTextField.text = posts[indexPath.row].username
cell.postContent.text = posts[indexPath.row].content
storageRef = FIRStorage.storage().reference(forURL: posts[indexPath.row].userImageUrlString)
storageRef.data(withMaxSize: 1 * 1024 * 1024, completion: { (data, error) in
if error == nil {
DispatchQueue.main.async {
if let data = data {
cell.UserImageView.image = UIImage (data: data)
}
}
}else {
print(error?.localizedDescription)
}
})
let storageRef2 = FIRStorage.storage().reference(forURL: posts[indexPath.row].PostImageUrlString)
storageRef2.data(withMaxSize: 1 * 1024 * 1024, completion: { (data, error) in
if error == nil {
DispatchQueue.main.async {
if let data = data {
cell.postImageView.image = UIImage (data: data)
}
}
}else {
print(error?.localizedDescription)
}
})
return cell
}
//done!!!! ------------------------------------------
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
tableView.deleteRows(at: [indexPath], with: .fade)
let ref = posts[indexPath.row].ref
ref!.removeValue()
posts.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var numberOfRows = 0
switch segmentedControl.selectedSegmentIndex {
case 0 : numberOfRows = posts.count
case 1: numberOfRows = posts.count
default: break
}
return numberOfRows
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 420.00
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segmentedControl.selectedSegmentIndex == 0 {
if segue.identifier == "addComment" {
let vc = segue.destination as! CommentTableViewController
let indexPath = tableView.indexPathForSelectedRow!
vc.selectedPosts = posts[indexPath.row]
}
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if segmentedControl.selectedSegmentIndex == 0 {
performSegue(withIdentifier: "addComment", sender: self)
}
if segmentedControl.selectedSegmentIndex == 1 {
performSegue(withIdentifier: "addComment", sender: self)
}
if segmentedControl.selectedSegmentIndex == 2 {
performSegue(withIdentifier: "addComment", sender: self)
}
}
func assignArray() {
let otherVC = CommentTableViewController()
kommentarArray = otherVC.commentsArray
print(kommentarArray.count)
}
}
The code for the CommentTableViewController ( where i want to get the count of comments from the array var commentsArray = FotoComment which is already working on this TableView)
import UIKit
import Firebase
import FirebaseAuth
import FirebaseDatabase
import FirebaseStorage
class CommentTableViewController: UITableViewController {
#IBOutlet weak var komentarZähler: UILabel!
#IBOutlet weak var UserImageView: UIImageView!
#IBOutlet weak var usernameTextField: UILabel!
#IBOutlet weak var postImageView: UIImageView!
#IBOutlet weak var postContent: UITextView!
var dataBaseRef : FIRDatabaseReference!
var storageRef : FIRStorageReference!
var commentsArray = [FotoComment]()
var selectedPosts:PostMitBild!
override func viewDidLoad() {
super.viewDidLoad()
configurePost()
let commentRef = selectedPosts.ref!.child("Kommentare")
commentRef.observe(.value, with: { (snapshot) in
var newComments = [FotoComment]()
for item in snapshot.children {
let neuerKommentar = FotoComment(snapshot: item as! FIRDataSnapshot)
newComments.insert(neuerKommentar, at: 0)
}
self.commentsArray = newComments
self.tableView.reloadData()
}, withCancel: { (error) in
print(error.localizedDescription)
})
}
#IBAction func addComment(_ sender: UIBarButtonItem) {
let alertView = UIAlertController(title: "Kommentar", message: "Füge einen Kommentar hinzu", preferredStyle: UIAlertControllerStyle.alert)
alertView.addTextField { (textfield) in
textfield.placeholder = "Einen neuen Kommentar hinzufügen"
}
let sendCommentAction = UIAlertAction(title: "Kommentieren", style: .default) { (action) in
let textfield = alertView.textFields!.first!
let comment = FotoComment(content: textfield.text! , postId: self.selectedPosts.postId , username: (FIRAuth.auth()!.currentUser!.displayName!) , userImageUrlString: String(describing: FIRAuth.auth()!.currentUser!.photoURL!), postDate: (NSDate().timeIntervalSince1970))
let commentRef = self.selectedPosts.ref!.child("Kommentare").childByAutoId()
commentRef.setValue(comment.toAnyObject())
}
let cancelAction = UIAlertAction(title: "Abbrechen", style: .cancel, handler: nil)
alertView.addAction(sendCommentAction)
alertView.addAction(cancelAction)
self.present(alertView, animated: true, completion: nil)
}
// 2----------------------------------------------
func configurePost() {
usernameTextField.text = selectedPosts.username
postContent.text = selectedPosts.content
storageRef = FIRStorage.storage().reference(forURL: selectedPosts.userImageUrlString)
storageRef.data(withMaxSize: 1 * 1024 * 1024, completion: { (data, error) in
if error == nil {
DispatchQueue.main.async {
if let data = data {
self.UserImageView.image = UIImage (data: data)
}
}
}else {
print(error?.localizedDescription)
}
})
let storageRef2 = FIRStorage.storage().reference(forURL: selectedPosts.PostImageUrlString)
storageRef2.data(withMaxSize: 1 * 1024 * 1024, completion: { (data, error) in
if error == nil {
DispatchQueue.main.async {
if let data = data {
self.postImageView.image = UIImage (data: data)
}
}
}else {
print(error?.localizedDescription)
}
})
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
komentarZähler.text = "Kommentare: \(commentsArray.count)"
return commentsArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "commentCell", for: indexPath) as! CommentTableViewCell
if let seconds = commentsArray[indexPath.row].postDate {
let timestamp = NSDate(timeIntervalSince1970: seconds)
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/yyyy HH:mm:ss"
cell.uploadDatum.text = dateFormatter.string(from: timestamp as Date)
}
cell.usernameTextField.text = commentsArray[indexPath.row].username
cell.postContent.text = commentsArray[indexPath.row].content
storageRef = FIRStorage.storage().reference(forURL: commentsArray[indexPath.row].userImageUrlString!)
storageRef.data(withMaxSize: 1 * 1024 * 1024, completion: { (data, error) in
if error == nil {
DispatchQueue.main.async {
if let data = data {
cell.UserImageView.image = UIImage (data: data)
}
self.tableView.reloadData()
}
}else {
print(error?.localizedDescription)
}
})
return cell
}
}
this is how i safe my data in firebase. I want to update the number of comments (kommentarAnzahl which is currently 0) every time a comment is added to the post
You have to convert your Array count to string value to display in cell.
Try this Code,
cell.kommentarZähler.text = String("Kommentare:",kommentarArray.count)
I hope this will work for You.
So you have two separate view controllers namely CommentTableViewController and MemesTableViewController consisting of commentsArray and kommentarArray resepctively. These arrays are of class-scope meaning that once you get outside of your class; for this case it would be leaving the view, then they would be deallocated. Once you enter the view, they'll be re-created again and filled with values.
Since you want to get the number of elements in commentsArray, I'd recommend you create a static variable which would keep track of this. When you make something static you're pretty much making it accessible throughout your entire app/program and changes made to it are reflected across the entire app. In other words, a memory block is reserved to store your variable which will only be de-allocated once you quit the app entirely. You may think of this as an app-scope variable.
Two ways
Lousy Way
Change your commentsArray definition from var commentsArray = [FotoComment]() to static var commentsArray = [FotoComment](). By doing this, then you may access and manipulate the contents of this array from any other class. This is great if you have few elements but what happens when you have tens of thousands or even a million comments? It'll mean that we'll be walking around with huge amounts of data everywhere even when we really don't need it.
Recommended Way
Keep your current commentsArray definition and add this static var numberOfComments: Int = 0 inside your CommentTableViewController. Right after adding your elements to commentsArray, update the element tracker as shown below
CommentTableViewController.numberOfComments = commentsArray.count
Then when you go back to your MemesTableViewController, you can simply delete assignArray(); since we have a global element counter now, and simply amend your cell to this
cell.kommentarZähler.text = String(CommentTableViewController.numberOfComments)
With this, even if you create say another class called FriendsVC, you can still access numberOfComments and even change it as well.
PS: Since numberOfComments is static, whenever and wherever you want to access or amend it, you MUST always first call the class or struct in which it was defined in. For this case, it is inside CommentTableViewController so you need to always do CommentTableViewController.numberOfComments to access it; even when you are inside CommentTableViewController itself. Always remember that.