How can I pass a Post Id to a Comments VC - Swift - swift

I am having trouble sending the postid to comments vc so that I can save it in Firebase.
I am following a tutorial online where we are building this architecture on Firebase however when I send the data to Firebase it is not capturing the postId as seen onthis screenshot. I'm obviously missing something. Would really appreciate it if someone could shed some light as to what my mistake could be. Below I'll put the Comments View Controller function where I send the data to Firebase.
#IBAction func sendButtonPressed(_ sender: UIButton) {
let ref = Database.database().reference()
let commentsReference = ref.child("comments")
let newCommentId = commentsReference.childByAutoId().key
let newCommentReference = commentsReference.child(newCommentId)
//current user information
guard let currentUser = Auth.auth().currentUser else {
return
}
let currentUserId = currentUser.uid
newCommentReference.setValue(["userid": currentUserId, "commentText": commentTextField.text!]) { (error, ref) in
if error != nil {
ProgressHUD.showError(error!.localizedDescription)
return
}
let postCommentRef = Database.database().reference().child("post-comments").child(self.postIdNew).child(newCommentId)
postCommentRef.setValue(true, withCompletionBlock: { (error, ref) in
if error != nil {
ProgressHUD.showError(error!.localizedDescription)
return
}
})
self.empty()
self.view.endEditing(true)
}
}
This is how I'm supposed to get the postId reference from the Home View Controller.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "commentSegue" {
let commentVC = segue.destination as! CommentViewController
let postId = sender as! String
commentVC.postIdNew = postId
}
}
Here are my collection view extensions
extension HomeViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView == self.lostCollectionView {
return posts.count
}
if collectionView == self.foundCollectionView {
return newPostsFound.count
}
if collectionView == self.adoptionCollectionView {
return postsadoption.count
}
else {
return 0
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
switch collectionView {
case lostCollectionView:
let lostcell: LostCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "Lostcell", for: indexPath) as! LostCollectionViewCell
let post = posts[indexPath.row]
let user = users[indexPath.row]
lostcell.post = post
lostcell.user = user
//Make TextView Clickable
lostcell.phoneLostTextView.isEditable = false;
lostcell.phoneLostTextView.dataDetectorTypes = UIDataDetectorTypes.phoneNumber
//Make Comments View Clickable
lostcell.homeVC = self
return lostcell
case foundCollectionView:
let foundcell: FoundCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "Foundcell", for: indexPath) as! FoundCollectionViewCell
let post = newPostsFound[indexPath.row]
foundcell.post = post
//Make TextView Clickable
foundcell.phoneFoundTextView.isEditable = false;
foundcell.phoneFoundTextView.dataDetectorTypes = UIDataDetectorTypes.phoneNumber
return foundcell
case adoptionCollectionView:
let adoptioncell: AdoptionCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "Adopotioncell", for: indexPath) as! AdoptionCollectionViewCell
let post = postsadoption[indexPath.row]
adoptioncell.post = post
//Make TextView Clickable
adoptioncell.phoneAdoptionTextView.isEditable = false;
adoptioncell.phoneAdoptionTextView.dataDetectorTypes = UIDataDetectorTypes.phoneNumber
return adoptioncell
default:
return UICollectionViewCell()
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
switch collectionView {
case lostCollectionView:
let vc = storyboard?.instantiateViewController(withIdentifier: "lostSelectedViewController") as? LostSelectedViewController
self.navigationController?.pushViewController(vc!, animated: true)
vc?.posts = posts[indexPath.row]
break
case foundCollectionView:
let vc = storyboard?.instantiateViewController(withIdentifier: "foundSelectedViewController") as? FoundSelectedViewController
self.navigationController?.pushViewController(vc!, animated: true)
vc?.posts = newPostsFound[indexPath.row]
break
case adoptionCollectionView:
let vc = storyboard?.instantiateViewController(withIdentifier: "adoptionSelectedViewController") as? AdoptionSelectedViewController
self.navigationController?.pushViewController(vc!, animated: true)
vc?.posts = postsadoption[indexPath.row]
break
default:
break
}
func commentsViewPressed() {
print("Hola")
performSegue(withIdentifier: "commentSegue", sender: self)
}
}
}

The issue looks like its in this code
let postId = sender as! String
commentVC.postIdNew = postId
Sender refers to the object that initiated the segue, so likely a button or TableViewCell (see apples docs: https://developer.apple.com/documentation/uikit/uiviewcontroller/1621490-prepare)
You need to replace sender as! String with the value of the postId that you are trying to set. I assume that you can get that from somewhere on the first view controller.

Actually my mistake was nowhere here. My mistake was that my snapshot.key was not retreiving the childByAutoId so when I ran the query it gave me a list of matching children and since there was no single result, the SDK prints the key of the location/collection that you queried: posts.
All I had to do was to retrieve the childByAutoId I had to use this line:
let key = childSnapshot.key as String
I found my answer in this stackoverflow question --> Firebase snapshot.key not returning actual key?

Related

dynamically load sections of UIController depending on data

I am trying to implement a UICollectionView for a "Add Friends" page in my application and I need the following functionality:
When the view first appears, display and friend requests that a user may have.
User inputs username into search bar, and then (if found) that username shows up in a cell ABOVE the cells for friend requests.
I have been trying to implement this by using sections in a UICollevtionViewController but it has been a headache...
import UIKit
import Firebase
class AddUserController: UICollectionViewController, UICollectionViewDelegateFlowLayout, UISearchBarDelegate {
var searchedUser: User?
var friendRequests = [User]()
let cellId = "cellId"
let headerId = "headerId"
var sectionCategories = ["Add Friends", "Friend Requests"]
override func viewDidLoad() {
super.viewDidLoad()
collectionView?.delegate = self
collectionView?.dataSource = self
collectionView?.register(SearchedUserCell.self, forCellWithReuseIdentifier: cellId)
collectionView?.register(SectionHeaderView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: headerId)
getFriendRequests()
}
fileprivate func fetchSearchedUsers(username: String) {
let ref = Database.database().reference().child("usernames")
ref.child(username).observeSingleEvent(of: .value, with: { (snapshot) in
// populate user info
guard let uidOfSearchedUser = snapshot.value as? String else {return}
Database.database().reference().child("users").child(uidOfSearchedUser).observeSingleEvent(of: .value, with: { (snapshot) in
guard let userDictionary = snapshot.value as? [String: Any] else {return}
self.searchedUser = User(uid: uidOfSearchedUser, dictionary: userDictionary)
self.collectionView?.reloadData()
}, withCancel: { (err) in
print("error retrieving user", err)
})
}) { (err) in
print("unable to find user: ", err)
}
}
func getFriendRequests() {
guard let uid = Auth.auth().currentUser?.uid else {return}
Database.database().reference().child("users").child(uid).child("requests").observe(.value) { (snapshot) in
guard let requestsDictionary = snapshot.value as? [String: Any] else {return}
for (key, value) in requestsDictionary {
print(key, value)
Database.database().reference().child("users").child(key).observeSingleEvent(of: .value, with: { (snapshot) in
guard let userDictionary = snapshot.value as? [String: Any] else {return}
let user = User(uid: key, dictionary: userDictionary)
print("friend request from: ", user.username)
self.friendRequests.append(user)
})
}
}
self.collectionView?.reloadData()
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if section == 0 {
return 4
} else if section == 1 {
return 1
}
return 0
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let sendFriendRequestcell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! SearchedUserCell
let dealWithFriendRequestCell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! SearchedUserCell
if indexPath.section == 0 {
//Cell for searched user
sendFriendRequestcell.user = searchedUser
return sendFriendRequestcell
} else if indexPath.section == 1 {
//Populate all the friend requests that exist
if friendRequests.count != 0 {
dealWithFriendRequestCell.user = friendRequests[indexPath.item]
}
return dealWithFriendRequestCell
}
return sendFriendRequestcell
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
//Change this to return only 2 only if friend requests exist.
return 2
}
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
switch kind {
case UICollectionElementKindSectionHeader:
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerId, for: indexPath) as! SectionHeaderView
headerView.sectionName = sectionCategories[indexPath.section]
return headerView
default:
assert(false, "Unexpected element kind")
}
}
}
Im using firebase to store/fetch both my searched users and any friend requests. I can see users in the friend requests.
The issues I'm having are:
Dynamically showing sections (the "Add Friends" section and cells shouldn't be displayed unless user searches for a user.
This particular user (screenshot) has a friend request, but the cell isn't populated to show that. I can see that I am retrieving user correctly.
Is a collection view like this even the best way for me to handle this? Seems a bit complicated.
I say your problem is state. Here is an example how state can be modeled with an enum with associated values. Read more on enums here.
struct User {}
struct UserRequest {}
class Controller: NSObject {
var collectionView: NSCollectionView!
enum Sections: Int {
case searched = 0
case requests = 1
}
enum State {
case none
case requests(requests: [UserRequest])
case searched(user: User)
case searchedAndRequests(user: User, requests: [UserRequest])
}
var state: State = .none {
didSet {
collectionView.reloadData()
}
}
}
extension Controller: NSCollectionViewDataSource {
func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
switch state {
case .requests(let requests):
return requests.count
case .searched(_):
return 1
case .searchedAndRequests(_, let requests):
switch Section(rawValue: section)! {
case .searched:
return 1
case .requests:
return requests.count
default:
fatalError("section not allowed.")
}
default:
fatalError("invalid state.")
}
}
func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
// Create cell(s) here or later.
switch state {
case .searched(let user):
// Populate user cell and return it.
break
case .requests(let requests):
let request = requests[indexPath.item]
// Populate cell with request and return it.
case .searchedAndRequests(let user, let requests):
switch Section(rawValue: indexPath.section)! {
case .searched:
// Populate user cell and return it.
break
case .requests:
let request = requests[indexPath.item]
// Populate cell with request and return it.
default:
fatalError("section not allowed.")
}
default:
fatalError("invalid state")
}
}
func numberOfSections(in collectionView: NSCollectionView) -> Int {
switch state {
case .none:
return 0
case .requests(_), .searched(_):
return 1
case .searchedAndRequests(_, _):
return 2
}
}
}

click on button in uicollection cell to segue

A have a button within a collectionviewcell and when I click on the button, the goal is to segue to a more detailed view controller.
class WelcomeViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate,UIGestureRecognizerDelegate, UISearchBarDelegate {
#IBOutlet weak var CollectionView: UICollectionView!
var databaseRef = FIRDatabase.database().reference()
var loggedInUser = FIRAuth.auth()?.currentUser
var dictDetails: [String:AnyObject]?
var posts = NSMutableArray()
let storage = FIRStorage.storage()
override func viewDidLoad() {
super.viewDidLoad()
(CollectionView.collectionViewLayout as! UICollectionViewFlowLayout).itemSize = CGSize(width: (self.view.frame.width - 10) / 2.4, height: (self.view.frame.width - 10) / 1.5 )
self.navigationItem.title = "Lit Swap"
CollectionView.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 300)
self.CollectionView.contentInset = UIEdgeInsetsMake(-65, 0, 0, 0)
definesPresentationContext = true
loadData()
}
#IBAction func editButtonTapped() -> Void {
print("Hello Edit Button")
performSegue(withIdentifier: "UsersProfile", sender: self)
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "UsersProfile" {
self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
if let indexPaths = self.CollectionView!.indexPathsForSelectedItems{
///I DONT THINK YOU SHOULD REFERENCE POST, REFERENCE BOOKS INSTEAD///////////////
// if let indexPaths = self.CollectionView.cellForItem(at: <#T##IndexPath#>){
let vc = segue.destination as! UsersProfileViewController
let cell = sender as! UICollectionViewCell
let indexPath = self.CollectionView!.indexPath(for: cell)
let post = self.posts[(indexPath?.row)!] as! [String: AnyObject]
// let username = post["username"] as? String
let userpicuid = post["uid"] as? String
// vc.username = username
vc.userpicuid = userpicuid
print(indexPath?.row)
}} }
}
func loadData(){
if (FIRAuth.auth()?.currentUser) != nil{
FIRDatabase.database().reference().child("books").observeSingleEvent(of: .value, with: { (snapshot:FIRDataSnapshot) in
let loggedInUserData = snapshot
if let postsDictionary = snapshot .value as? [String: AnyObject] {
for post in postsDictionary {
self.posts.add(post.value)
}
self.CollectionView.reloadData()
}})}
}
// Properties of the UICollectionView
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int{
return self.posts.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! PinterestLikeCollectionViewCell
//configure the cell...
if (FIRAuth.auth()?.currentUser) != nil{
print(posts[indexPath.row])
let post = self.posts[indexPath.row] as! [String: AnyObject]
cell.Title.text = post["title"] as? String
cell.Author.text = post["Author"] as? String
let editButton = UIButton(frame: CGRect(x: 8, y: 225, width: 154, height: 45))
editButton.addTarget(self, action: #selector(editButtonTapped), for: UIControlEvents.touchUpInside)
editButton.tag = indexPath.row
print(indexPath.row)
editButton.isUserInteractionEnabled = true
cell.addSubview(editButton)
if let imageName = post["image"] as? String {
let imageRef = FIRStorage.storage().reference().child("images/\(imageName)")
imageRef.data(withMaxSize: 25 * 1024 * 1024, completion: { (data, error) -> Void in
if error == nil {
let image = UIImage(data: data!)
cell.Books.image = image
cell.Books.roundCornersForAspectFit(radius: 10)
cell.Books.clipsToBounds = true
}else {
print("Error downloading image:" )
}})}}
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: CGFloat((collectionView.frame.size.width / 5) - 20), height: CGFloat(500))
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "details" {
self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
if let indexPaths = self.CollectionView!.indexPathsForSelectedItems{
let vc = segue.destination as! BookDetailsViewController
let cell = sender as! UICollectionViewCell
let indexPath = self.CollectionView!.indexPath(for: cell)
let post = self.posts[(indexPath?.row)!] as! [String: AnyObject]
let Booked = post["title"] as? String
let Authors = post["Author"] as? String
let ISBNS = post["ISBN"] as? String
let Prices = post["Price"] as? String
let imageNames = post["image"] as? String
let imagesTwo = post["imageTwo"] as? String
let imagesThree = post["imageThree"] as? String
let imagesFour = post["imageFour"] as? String
let imagesFive = post["imageFive"] as? String
vc.Booked = Booked
vc.Authors = Authors
vc.ISBNS = ISBNS
vc.Prices = Prices
vc.imageNames = imageNames
vc.imagesTwo = imagesTwo
vc.imagesThree = imagesThree
vc.imagesFour = imagesFour
vc.imagesFive = imagesFive
print(indexPath?.row)
} }}
}
However, it does not do anything. I currently have my cell setup that when you click on it, it segues to a detailed view controller. But the button within the cell, when clicked should go to a different detailed view controller. For the cell's segue, the information to segue what put in the didSelectItemAt function. I am not sure what function to include the segue for the button in the cell.
Can you include your class as whole so I can get a better understanding of how your configuring the views? I'll update my answer with what I think would help, from what there's I think there a few different things that could be happening to cause this.
UPDATE
Try this:
Create and add your button in your PinterestLikeCollectionViewCell class.
Make a protocol that will tell it's delegate to preform your your action when the cell button is clicked.
Assign your WelcomeViewController class as that delegate and conform to the protocol.

Error when peeking and popping from collection view

Received an error
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
when trying to peek and pop from a collection view. I've checked my data struct and index path but everything seems to be fine.
Here's my code for the collections view
class thisSeaonViewController: UICollectionViewController, UIViewControllerPreviewingDelegate {
#IBOutlet weak var activityIndicator: UIActivityIndicatorView!
var URLArrayStringThisSeason = [String]()
var currentURL = String()
override func viewDidLoad() {
generateData()
if( traitCollection.forceTouchCapability == .available){
registerForPreviewing(with: self as! UIViewControllerPreviewingDelegate, sourceView: view)
}
}
override func viewDidAppear(_ animated: Bool) {
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
let imageView = cell.viewWithTag(1) as! UIImageView
let url = NSURL(string: URLArrayStringThisSeason[indexPath.row])
let placeholderImage = UIImage(named: "Rectangle")!
let filter = AspectScaledToFillSizeWithRoundedCornersFilter(
size: imageView.frame.size,
radius: 0
)
imageView.af_setImage(withURL: url as! URL, placeholderImage: placeholderImage, filter: filter, imageTransition: .crossDissolve(0.2)
)
cell.backgroundColor = UIColor.init(hexString: "#F3F3F3")
cell.layer.cornerRadius = 3.0
return cell
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return URLArrayStringThisSeason.count
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let vc = storyboard?.instantiateViewController(withIdentifier: "gridDetailedView") as! gridDetailedViewController
vc.imageURL = URLArrayStringThisSeason[indexPath.row]
self.navigationController?.pushViewController(vc, animated: true)
}
func generateData() {
if URLArrayStringThisSeason.count == 0 {
self.activityIndicator.isHidden = false
self.activityIndicator.startAnimating()
}
let queryThisSeason = FIRDatabase.database().reference().child("thisSeason")
queryThisSeason.keepSynced(true)
queryThisSeason.observeSingleEvent(of: .value, with: {(snapshot) in
if snapshot.childrenCount != 0 {
let urlArray = snapshot.value as! [String]
let urlLimitedArray = Array(urlArray.reversed())
self.URLArrayStringThisSeason = urlLimitedArray
self.collectionView?.reloadData()
self.activityIndicator.stopAnimating()
self.activityIndicator.isHidden = true
}
})
}
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
guard let indexPath = collectionView?.indexPathForItem(at: location) else { return nil }
guard let cell = collectionView?.cellForItem(at: indexPath) else { return nil }
guard let detailVC = storyboard?.instantiateViewController(withIdentifier: "gridDetailedView") as? gridDetailedViewController else { return nil }
//let photo = UIImage(named: "Rectangle")
detailVC.imageURL = URLArrayStringThisSeason[indexPath.row]
print(URLArrayStringThisSeason[indexPath.row])
detailVC.preferredContentSize = CGSize(width: 300, height: 300)
previewingContext.sourceRect = cell.frame
print("peek")
return detailVC
}
func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
self.navigationController?.show(viewControllerToCommit, sender: Any?.self)
print("pop")
}
}
when peeking and popping, the function is supposed to send the imageURL to the detailed view controller and AlamofireImage will handle the image download and loading.
However, I've been getting misalignment issues with the collections view as the source rect will appear slightly above the cells and preventing peek and pop at certain parts of the cell. I think that this could be the cause of the peek and pop crash too.
edit:
here's what happens when I try to do peek and pop, you can see the focus of the cell is slightly shifted on top.
Ok I fixed the misalignment problem by changing this registerForPreviewingWithDelegate(self, sourceView: view)
to this
registerForPreviewingWithDelegate(self, sourceView: self.collectionView!)
however, the app is still crashes everytime I try to peek and pop.
Edit:
Ok the other problem is pretty much just some errors in the code. Just follow the above to fix the misalignment problem.

Empty Collection View Swift

I followed 1 tutorial and i was able to fill a collectionView with some data(imageview and text):
let appleProducts = ["A", "B", "C", "D"]
let imageArray = [UIImage(named: "pug1"), UIImage(named: "pug2"), UIImage(named: "pug3"), UIImage(named: "pug4")]
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return appleProducts.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath as IndexPath) as! CollectionViewCell
cell.imageView?.image = self.imageArray[indexPath.row]
cell.title?.text = self.appleProducts[indexPath.row]
return cell
}
Now passing from the demo project to mine, I want to fill this CollectionView with data(Picture and text) that I get from FirebaseDatabse so I created this method:
struct item {
let pictureId: String!
let picture: String!
}
var items = [item]()
func getLatestAddedItems(){
self.items.removeAll()
let databaseRef = FIRDatabase.database().reference()
databaseRef.child("Items").observe(.value, with: {
snapshot in
//self.items.insert(item(picture: picture), at: 0)
for childSnap in snapshot.children.allObjects {
let snap = childSnap as! FIRDataSnapshot
//print(snap.key)
let picture = (snap.value as? NSDictionary)?["bookImage"] as? String ?? ""
//print(picture)
self.items.append(item(pictureId:snap.key, picture:picture))
}
print(self.items.count)
})
}
And I create this button to call GetLatestAddedItems Method:
#IBAction func selectAction(_ sender: AnyObject) {
getLatestAddedItems()
}
And this one to check results:
#IBAction func gettableAction(_ sender: AnyObject) {
print(self.items[0].picture)
print(self.items[1].picture)
print(self.items[2].picture)
print(self.items.count) }
OutPut results:
picture 1 link
picture 2 link
picture 3 link
3
Everythings look fine and correct, now after making required changes in ContentView methods:
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return items.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath as IndexPath) as! CollectionViewCell
//cell.imageView?.image = self.imageArray[indexPath.row]
let url = NSURL(string: items[indexPath.row].picture)
let data = NSData(contentsOf: url! as URL)
cell.imageView?.image = UIImage(data: data! as Data)
cell.title?.text = self.items[indexPath.row].pictureId
return cell
}
Now I'm getting an empty ContentView, the first time with button it works because I call the getLatestAddedItems() that will get and add data to the Items table, I try to call it in both ViewWillAppear or Viewdidload but nothings changes.
This is what I think the return items.count is returning 0 so nothings will appear any suggestions ?
Move your collectionView's protocol delegation initialisation to one of the ViewController lifecycle scope such as viewDidLoad() or viewWillAppear(_animated : Bool) if you are using a custom viewController(i.e embed a collectionView inside a viewController)
And reload your collectionView every time your user receives a value from its database.
override func viewDidLoad(){
super.viewDidLoad()
self.collectionView.dataSource = self
self.collectionView.delegate = self
}
func getLatestAddedItems(){
self.items.removeAll()
let databaseRef = FIRDatabase.database().reference()
databaseRef.child("Items").observe(.childAdded, with: {
snapshot in
for childSnap in snapshot.children.allObjects {
let snap = childSnap as! FIRDataSnapshot
let picture = (snap.value as? NSDictionary)?["bookImage"] as? String ?? ""
self.items.append(item(pictureId:snap.key, picture:picture))
print(self.items.count)
self.collectionView.reloadData()
}
})
}
PS:- All the calls to your firebase server are asynchronous, which takes some time to retrieve the data from your FBDB, so put print(self.items.count) should be inside the completionBlock of the firebase observing call otherwise if it is put outside it will be called even before your data has been retrieved from FBDB.

How could I make the SWRevealViewController available on all my scene?

I am creating an App on Xcode7 using swift and I really need some help. I would like to make the SWRevealViewController sidebar appear on all of my scene but the problem is it only appears on the first view controller I set the push segue to show. And also upon clicking a link on the sidebar the navigation bar disappears on the next scene? Please somebody help...
sidebar
Here is the script I used on my UITableViewController for the sidebar links
var catArrayId = [String]()
var catArrayName = [String]()
var catArrayImg2 = [String]()
override func viewDidLoad(){
// get available categories according to customer country
get_categories()
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return catArrayId.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("navCell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = self.catArrayName[indexPath.row]
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("showCategory", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showCategory" {
let VC = segue.destinationViewController as! CategoryProductsViewController
let indexPath: NSIndexPath = self.tableView.indexPathForSelectedRow!
let categoryImage = UIImage(named: catArrayImg2[indexPath.row])
VC.catId = self.catArrayId[indexPath.row]
VC.image = categoryImage!
}
}
func get_categories(){
let country_id = 168
//let startTime = NSDate.timeIntervalSinceReferenceDate()
let pageUrl = "https://domain.com/ios/home-categories-image.php?country_id=\(country_id)&uudi=" + NSUUID().UUIDString
let myUrl = NSURL(string: pageUrl)
let request = NSMutableURLRequest(URL: myUrl!)
request.HTTPMethod = "GET"
request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringCacheData
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request){
(let data, let response, let error) in
if(error != nil){
print(error?.localizedDescription)
return
}
do{
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments)
let catArray = json as? [[String: AnyObject]]
for catArr in catArray!{
let catName = catArr["name"] as? String
let catID = catArr["id"] as? String
let img2 = catArr["image2"] as? String
dispatch_async(dispatch_get_main_queue(), {
self.catArrayId.append(catID!)
self.catArrayName.append(catName!)
self.catArrayImg2.append(img2!)
self.tableView.reloadData()
})
}
}
catch{
print("Error serializing JSON: \(error)")
}
}
task.resume()
}
If I understood your question right, then you can do the same as in example provided by an author of controller ("RevealControllerStoryboardExample2"). When you select something from rear VC, segue for that action needs to have class "SWRevealViewControllerSeguePushController". Here is a screenshot of this example: