Cells for TableView are not showing - ios

I am trying to program a social media app and I want the posts to appear in the cells. The only things in the cell are a label for the post and a label for the topic. When I run the code there are no errors but the cells are not showing in the table. I cannot seem to figure out the problem. Thank you for your guys help.
import UIKit
import Firebase
import FirebaseDatabase
import FirebaseStorage
import FirebaseAuth
import SwiftKeychainWrapper
class FeedVC: UIViewController, UITableViewDelegate, UITableViewDataSource, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet weak var postBtn: UIButton!
#IBOutlet var tableView: UITableView!
var posts = [Post]()
var post: Post!
var userName: String!
var refPosts: DatabaseReference!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
//getting a reference to the node posts
refPosts = Database.database().reference().child("posts")
//observing the data changes
refPosts.observe(DataEventType.value, with: { (snapshot) in
//if the reference have some values
if snapshot.childrenCount > 0 {
//clearing the list
self.posts.removeAll()
//iterating through all the values
for data in snapshot.children.allObjects as! [DataSnapshot] {
//getting values
let postObject = data.value as? [String: AnyObject]
let id = postObject?["id"]
let thought = postObject?["thought"]
let likes = postObject?["likes"]
//creating artist object with model and fetched values
let post = Post(_id: id as! String, _thought: thought as! String?, _likes: likes as! Int?)
//appending it to list
self.posts.append(post)
}
//reloading the tableview
self.tableView.reloadData()
}
})
/*refPosts.observe(.value, with: {(snapshot) in
if let snapshot = snapshot.children.allObjects as? [DataSnapshot] { //all objects in snapshot
self.posts.removeAll()
for data in snapshot {
print(data)
if let postDict = data.value as? Dictionary<String, AnyObject>{
let key = data.key
let post = Post(postKey: key, postData: postDict)
self.posts.append(post)
}
}
}
self.tableView.reloadData()
})*/
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let post = posts[indexPath.row]
if let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell") as? PostCell{
cell.configCell(post: post)
return cell
}else{
return PostCell()
}
}
func PostToFirebase(imgUrl: String){
let userID = Auth.auth().currentUser?.uid
Database.database().reference().child("users").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
if let data = snapshot.value as? Dictionary<String, AnyObject>{
//if let snap = snapshot.value as? [String:Any] {
let data = snapshot.value as! Dictionary<String, AnyObject>
let username = data["username"]
let post: Dictionary<String, AnyObject> = [
"username": username as AnyObject,
"likes": 0 as AnyObject
]
let firebasePost = Database.database().reference().child("posts").childByAutoId()
firebasePost.setValue(post)
self.tableView.reloadData()
}
})
}
#IBAction func postImageTapped(_ sender: AnyObject){//leads to text field box -> What are you thinking?
//present(imagePicker, animated: true, completion: nil)
//performSegue(withIdentifier: "UploadPage", sender: nil)
}
#IBAction func SignOut (_ sender: AnyObject){
try! Auth.auth().signOut()
KeychainWrapper.standard.removeObject(forKey: "uid")
dismiss(animated: true, completion: nil)
}
}

As #vadian mentioned in the comments, forcing the cast would be fine in this scenario considering you have everything setup correctly. Try adding the print statements I have below so you can see in more detail what it happening with the cells.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let post = posts[indexPath.row]
if let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell") as? PostCell {
print("dequeueing cell")
cell.configCell(post: post)
return cell
}else{
print("initialising cell")
return PostCell()
}
}
The solution involves using the newer dequeue method that takes an index path and forcing the cast.
let post = posts[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell", for: indexPath) as! PostCell
cell.configCell(post: post)
return cell

Related

How is fetching parameters of a child different than fetching a child without parameters?

I changed it so that a child has multiple parameters(image and caption) instead of just being an image child.
This is what I have as relevant code.
class MyUser {
var UserFirstName: String?
var PhotoPosts: String?
init(UserFirstName: String?, Photos: String?) {
self.Photos = Photos
self.UserFirstName = UserFirstName
}
}
var peeps = [MyUser]()
public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ViewControllerTableViewCell
let image1 = cell.viewWithTag(1) as! UIImageView
let person: MyUser = peeps[indexPath.row]
cell.lblName.text = person.UserFirstName
if let Photos = person.Photos {
let url = URL(string: Photos)
image1.sd_setImage(with: url)
}
return cell
}
And
musicians.observe(DataEventType.value, with: {snapshot in
for peeps in snapshot.children.allObjects as! [DataSnapshot] {
if peeps.key != thisUsersUid {
let peepsObject = people.value as? [String: AnyObject]
let peepsUserFirstName = peopleObject?["UserFirstName"] as? String
let peepsPhotos = peopleObject?["Photos"] as? String
let RAA = MyUsers(Photos: peepsPhotos, UserFirstName: peepsUserFirstName)
self.peeps.append(RAA)
}
self.table.reloadData()
}
}
I'd like it to fetch the image parameter of the child and not look for the image only behind the child reference.

Retrieve image from firebase storage to show on tableView cell

I just need help I building Instagram-clone with firebase and I have an issue whit post feed I can't Retrieve image from firebase storage to show on tableView cell can you help me, please :(
import UIKit
import FirebaseAuth
import FirebaseDatabase
class HomeViewController: UIViewController ,UITableViewDelegate {
#IBOutlet weak var tableview: UITableView!
var posts = [Post]()
override func viewDidLoad() {
super.viewDidLoad()
tableview.dataSource = self
loadposts()
// var post = Post(captiontxt: "test", photoUrlString: "urll")
// print(post.caption)
// print(post.photoUrl)
}
func loadposts() {
Database.database().reference().child("posts").observe(.childAdded){ (snapshot: DataSnapshot)in
print(Thread.isMainThread)
if let dict = snapshot.value as? [String: Any]{
let captiontxt = dict["caption"] as! String
let photoUrlString = dict["photoUrl"] as! String
let post = Post(captiontxt: captiontxt, photoUrlString: photoUrlString )
self.posts.append(post)
print(self.posts)
self.tableview.reloadData()
}
}
}
#IBAction func logout(_ sender: Any) {
do {
try Auth.auth().signOut()
}catch let logoutErrorr{
print(logoutErrorr)
}
let storyboard = UIStoryboard(name: "Start", bundle: nil)
let signinVC = storyboard.instantiateViewController(withIdentifier: "SigninViewController")
self.present(signinVC, animated: true, completion: nil)
}
}
extension HomeViewController: UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableview.dequeueReusableCell(withIdentifier: "imagecell", for: indexPath) as! PostCellTableViewCell
cell.captionLabel.text = posts[indexPath.row].caption
cell.postimage.image = posts[indexPath.row].photoUrl
// print(cell.captionLabel.text)
// print(cell.daysLabel.text)
return cell
}
}
enter code here
import Foundation
class Post {
var caption: String
var photoUrl: String
init(captiontxt: String, photoUrlString: String) {
caption = captiontxt
photoUrl = photoUrlString
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableview.dequeueReusableCell(withIdentifier: "imagecell", for: indexPath) as! PostCellTableViewCell
cell.postimage.image = nil
cell.tag += 1
let tag = cell.tag
cell.captionLabel.text = posts[indexPath.row].caption
let photoUrl = posts[indexPath.row].photoUrl
getImage(url: photoUrl) { photo in
if photo != nil {
if cell.tag == tag {
DispatchQueue.main.async {
cell.postimage.image = photo
}
}
}
}
return cell
}
func getImage(url: String, completion: #escaping (UIImage?) -> ()) {
URLSession.shared.dataTask(with: URL(string: url)!) { data, response, error in
if error == nil {
completion(UIImage(data: data!))
} else {
completion(nil)
}
}.resume()
}

Swift 3 / Alamofire : I am not able to fetch the data on UITableView

I am using Alamofire and trying to fetch data on my tableview, however I am not able to get the data. When I use the cmd Print, its showing me the data but not able to fetch the data. How can I fetch the data on my tableview?
Please find the code below:-
import UIKit
import Alamofire
import SwiftyJSON
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, NSURLConnectionDelegate {
//let myarray = ["item1", "item2", "item3"]
var tableData = Array<Group>()
var arrRes = [[String:AnyObject]]() //Array of dictionary
var group = [Group]()
#IBOutlet weak var tableview: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
loadGroups()
}
func loadGroups(){
let testhappyhour:Group = Group(tempName: "TEST", tempID: "TESST", icons: "TEST", tempgbcount: "TEST")
self.group.append(testhappyhour)
//let groupQuery:String = "http://jsonplaceholder.typicode.com/users"
Alamofire.request("http://jsonplaceholder.typicode.com/users").responseJSON
{ response in switch response.result {
case .success(let JSON):
let response = JSON as! NSArray
for item in response { // loop through data items
let obj = item as! NSDictionary
let happyhour = Group(tempName:obj["NAME"] as! String, tempID:obj["id"] as! String, icons:obj["icon"] as! String, tempgbcount:obj["TOTAL"] as! String)
self.group.append(happyhour)
}
self.tableview.reloadData()
case .failure(let error):
print("Request failed with error: \(error)")
}
}
}
func convertToArray(text: String) -> [Any]? {
if let data = text.data(using: .utf8) {
do {
return try JSONSerialization.jsonObject(with: data, options: []) as? [Any]
} catch {
print(error.localizedDescription)
}
}
return nil
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
tableview.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//return myarray.count
return arrRes.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//let cell = tableView.dequeueReusableCell(withIdentifier: "groupCell", for: indexPath) as! UITableViewCell
// cell.textLabel?.text = myarray[indexPath.item]
let cell : UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "groupCell")!
var dict = arrRes[indexPath.row]
cell.textLabel?.text = dict["NAME"] as? String
cell.detailTextLabel?.text = dict["TOTAL"] as? String
return cell
}
}
Thank you!!
Need to change loadGroups function like this
func loadGroups(){
let testhappyhour:Group = Group(tempName: "TEST", tempID: "TESST", icons: "TEST", tempgbcount: "TEST")
self.group.append(testhappyhour)
Alamofire.request("http://jsonplaceholder.typicode.com/users").responseJSON
{ response in switch response.result {
case .success(let JSON):
let response = JSON as! NSArray
for item in response { // loop through data items
let obj = item as! NSDictionary
let happyhour = Group(tempName:obj["NAME"] as! String, tempID:obj["id"] as! String, icons:obj["icon"] as! String, tempgbcount:obj["TOTAL"] as! String)
self.group.append(happyhour)
self.arrRes.append(obj) // ADD THIS LINE
}
self.tableview.reloadData()
case .failure(let error):
print("Request failed with error: \(error)")
}
}
}
Array 'group' is appended with the Alamofire responses, but Array 'arrRes' is used as the table view data source. If you use self.group instead of arrRes in the data source methods, the table should update with the new groups received in the Alamofire response.

How to put text into a segue function to pass to next controller?

I want to take the title and put it as titleText in the DestVC which is a label. How do I put it in the segue function?
import UIKit
import Firebase
import FirebaseDatabase
import SDWebImage
struct postStruct {
let title : String!
let author : String!
let date : String!
let article : String!
let downloadURL : String!
}
class ZeroHomeViewController: UITableViewController {
var posts = [postStruct]()
var downloadURL : String = ""
override func viewDidLoad() {
super.viewDidLoad()
let ref = Database.database().reference().child("Posts")
ref.observeSingleEvent(of: .value, with: { snapshot in
print(snapshot.childrenCount)
for rest in snapshot.children.allObjects as! [DataSnapshot] {
guard let value = rest.value as? Dictionary<String,Any> else { continue }
guard let title = value["Title"] as? String else { continue }
guard let downloadURL = value["Download URL"] as? String else { continue }
guard let author = value["Author"] as? String else { continue }
guard let date = value["Date"] as? String else { continue }
guard let article = value["Article"] as? String else { continue }
let post = postStruct(title: title, author: author, date: date, article: article, downloadURL: downloadURL)
self.posts.append(post)
}
self.posts = self.posts.reversed(); self.tableView.reloadData()
})
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
let label1 = cell?.viewWithTag(1) as! UILabel
label1.text = posts[indexPath.row].title
let imageView = cell?.viewWithTag(2) as! UIImageView
let post = self.posts[indexPath.row];
imageView.sd_setImage(with: URL(string: post.downloadURL), placeholderImage: UIImage(named: "placeholder"))
return cell!
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "detail" {
if let indexPath = tableView.indexPathForSelectedRow {
let destVC = segue.destination as! ArticleViewController
destVC.titleText = value["Title"] as? String
}
}
}
}
You simply need to access the relevant postStruct from your posts array and then get the title. You already have the index path for the selected row; the .row property will be the index in your posts array for the struct you need.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "detail" {
if let indexPath = tableView.indexPathForSelectedRow {
let destVC = segue.destination as! ArticleViewController
destVC.titleText = posts[indexPath.row].title
}
}
}

Can't access Firebase child

I have a firebase database reference
FIRDatabase.database().reference().child("messages").child("\(self.convoId!)").childByAutoId()
I want to access the ReceiverName from my firebase database in DisplayViewController, but when I call the database reference, I get an error because of convoId. This is how convoId was declared (in MessagesViewController).
override func viewDidLoad() {
super.viewDidLoad()
let receiverId = receiverData as! String
let receiverIdFive = String(receiverId.characters.prefix(5))
let senderIdFive = String(senderId.characters.prefix(5))
if (senderIdFive > receiverIdFive)
{
self.convoId = senderIdFive + receiverIdFive
}
else
{
self.convoId = receiverIdFive + senderIdFive
}
}
receiverData was passed from UserviewController to MessagesViewController and "senderId" is the string identifier that uniquely identifies the current user sending messages and is automatically declared in JSQMessagesViewController.h. so essentially, I can't redeclare convoId in my DisplayViewController. However, in DisplayViewController, I need to access ReceiverName.
This is how I attempted to retrieve ReceiverName:
let rootRef = FIRDatabase.database().reference()
rootRef.child("messages").observeSingleEvent(of: .value) {
(snapshot: FIRDataSnapshot) in
let loggedInUserData = snapshot
if let postsDictionary = snapshot .value as? [String: AnyObject] {
for post in postsDictionary {
self.messages.add(post.value)
}
self.MessageTableView.reloadData()
}
}
Then I populate the derived data in a tableviewcell:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MessageCell", for: indexPath) as! MessageTableViewCell
//Configure the cell
print(messages[indexPath.row])
let message = self.messages[indexPath.row] as! [String: AnyObject]
cell.SellerName.text = message["ReceiverName"] as? String
return cell
}
Try this inside your observeSingleEvent function:
...
for post in postsDictionary {
let messages = post.value as! [String: AnyObject]
for (id, value) in messages {
let info = value as! [String: AnyObject]
let receiver = info["ReceiverName"]!
print("\(id): \(receiver)")
self.messages.add(value)
}
}
...

Resources