click on button in uicollection cell to segue - swift

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.

Related

Collectionview with coredata problems

The problem is when I switch between pages (TabNavigation) and I return in this page, a cell is added unwantedly, I rewrite the code the code many times, can someone help me?
CoreData is implemented it to save favorites in this collection view, and everything works except this little bug
var Distance : String!
var Logo : UIImage!
var pp : String!
var menuu : UIButton!
var loc : String!
var shop: [NSManagedObject] = []
#IBOutlet weak var ShopCollectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
ShopCollectionView.layer.cornerRadius = 10
ShopCollectionView.layer.masksToBounds = true
// register cell
let nibCell = UINib(nibName: ShopCollectionViewCellId, bundle: nil)
ShopCollectionView.register(nibCell, forCellWithReuseIdentifier: ShopCollectionViewCellId)
ShopCollectionView.delegate = self
ShopCollectionView.dataSource = self
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .sound]) { (granted, error) in }
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "ShopsData", in: managedContext)!
let item = NSManagedObject(entity: entity, insertInto: managedContext)
let fetch = NSFetchRequest<NSFetchRequestResult>(entityName: "ShopsData")
do {
let result = try? managedContext.fetch(fetch) as? [ShopsData]
shop = result ?? []
} catch {
fatalError()
}
collectionView.reloadData()
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of items
return shop.count + 1
}
<This is my writed method>
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.row >= shop.count {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ShopCollectionViewCellId, for: indexPath) as! ShopCollectionViewCell
return cell
} else {
let shop = shop[indexPath.row]
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ShopCollectionViewCellId, for: indexPath) as! ShopCollectionViewCell
cell.People.text = shop.value(forKey: "actualCustomers") as? String
cell.Location.text = shop.value(forKey: "location") as? String
return cell
}
}
This is the code I write
In your numberOfItemsInSection you return shop.count + 1 which means you are telling your collection view to show you 1 additional cell than the actual data you have.
Then in your cellForItemAt indexPath, you handle this by creating 1 blank cell.
If suggest you make the following changes to these functions as shown below and perhaps you will see the results you expect
override func collectionView(_ collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int
{
return shop.count
}
override func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let shop = shop[indexPath.row]
let cell =
collectionView.dequeueReusableCell(withReuseIdentifier: ShopCollectionViewCellId,
for: indexPath) as! ShopCollectionViewCell
cell.People.text = shop.value(forKey: "actualCustomers") as? String
cell.Location.text = shop.value(forKey: "location") as? String
return cell
}

CollectionViewCell is no displayed receiving data from Firebase

I have to fill the cells with data from the firebase. But they are not displayed. Help and explain where I made a mistake.
How to fill cell data ?
class TrainingProgramViewController: UIViewController {
#IBOutlet weak var collectionView: UICollectionView!
//var trainingPrograms = TrainingProgram.fetchTrainingProgram()
var trainingPrograms = [TrainingProgram]()
let cellScale: CGFloat = 0.7
override func viewDidLoad() {
super.viewDidLoad()
fetchPrograms()
}
func fetchPrograms() {
Database.database().reference().child("programs").observe(.childAdded) { (snapshot) in
if let dict = snapshot.value as? [String: Any] {
print(dict)
let newTitle = dict["title"] as! String
print("Новый тайтл:" + newTitle)
let newDescription = dict["description"] as! String
let trainingCell = TrainingProgram(description: newDescription, title: newTitle)
self.trainingPrograms.append(trainingCell)
print(self.trainingPrograms)
}
}
}
}
extension TrainingProgramViewController: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return trainingPrograms.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TrainingProgramCollectionViewCell", for: indexPath) as! TrainingProgramCollectionViewCell
let trainingProgram = trainingPrograms[indexPath.item]
cell.trainingPrograms = trainingProgram
return cell
}
This is a model:
class TrainingProgram
{
var description = ""
var title = ""
init(description: String, title: String) {
self.description = description
self.title = title
}
}
This is my structure of Database :
You forget to reload your collectionView
func fetchPrograms() {
Database.database().reference().child("programs").observe(.childAdded) { (snapshot) in
if let dict = snapshot.value as? [String: Any] {
print(dict)
let newTitle = dict["title"] as! String
print("Новый тайтл:" + newTitle)
let newDescription = dict["description"] as! String
let trainingCell = TrainingProgram(description: newDescription, title: newTitle)
self.trainingPrograms.append(trainingCell)
print(self.trainingPrograms)
}
DispatchQueue.main.async {
self. collectionView.reloadData()
}
}
}
Also set
collectionView.delegate = self
collectionView.dataSource = self
In your collectionView Method
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TrainingProgramCollectionViewCell", for: indexPath) as! TrainingProgramCollectionViewCell
cell.titleLabel.text = trainingPrograms[indexPath.item].title
return cell
}
After you fetch the data and append it to your array which is shown in your tableView/collectionView you always have to reloadData() like collectionView.reloadData() or tableView.reloadData()

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 to store image from collectionviewcell to core data

I have an entity called Task where taskImage is an attribute of binary data. I have the following
#IBOutlet weak var collectionView: UICollectionView!
var imageSelected = [UIImage]()
Then I have collection view as follows
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.imageSelected.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
as! EditCollectionViewCell
cell.imageView?.image = imageSelected[(indexPath as NSIndexPath).row]
cell.layer.borderColor = UIColor.white.cgColor
cell.layer.borderWidth = 3
return cell
}
Now I am trying to save image to core data when Save bar button item is pressed as follows
#IBAction func saveBtnPressed(_ sender: AnyObject) {
if #available(iOS 10.0, *) {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let task = Task(context: context)
task.taskDesc = taskText.text!
//task.taskImage = UIImagePNGRepresentation(cell.imageView?.image)
} else {
// Fallback on earlier versions
}
I am getting error for taskImage, any help regarding storing image will be appreciated.
My code to store image in core data
let appDel:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context:NSManagedObjectContext = appDel.managedObjectContext
let newContact = NSEntityDescription.insertNewObjectForEntityForName("Contact", inManagedObjectContext: context)
let imageData:NSData = UIImageJPEGRepresentation(imgViewPhoto.image!, 1)!
newContact.setValue(imageData, forKey: "imageData")
and retrieve it from coredata
let imageData:NSData = contact.valueForKey("imageData") as! NSData
imgViewPhoto.image = UIImage(data: imageData, scale: 1)