I have UICollectionView with custom cell (xib file), I manage to display the collectionview but I don't manage to detect when I tap on a cell with the function :
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath){
Usually, I manage to do that, but this time I don't know why it doesn't work. Actually I'm using this pods "https://cocoapods.org/pods/SACollectionViewVerticalScalingFlowLayout"
My code is :
class ProjectsController: UIViewController {
#IBOutlet weak var collectionViewGridFormat: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
collectionViewGridFormat.registerNib(UINib(nibName: "ProjectsGridFormatCell", bundle: nil), forCellWithReuseIdentifier: "cellProjectGrid")
...
}
}
extension ProjectsController: UICollectionViewDataSource, UICollectionViewDelegate {
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 30
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell : ProjectsGridFormatCell = collectionView.dequeueReusableCellWithReuseIdentifier("cellProjectGrid", forIndexPath: indexPath) as! ProjectsGridFormatCell
cell.lblProjectName.text = "Test project"
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath){
print("aa")
}
}
But when I tap on a cell, "print("aa")" is not displayed.
Have I given enough information ? :)
Thanks for your help !! :D
Regards,
Is "User Interaction Enabled" checked under the Identity Inspector in Storyboard?
Related
I am trying to display a xib of a collectionViewCell from the tableViewCell (so I can do both horizontal and vertical scrolling while having categories per row). It seems that the register of the xib is where the issue is coming into play as it will not register it properly from the proper place? tableView cannot be registering it since it fails when I tried to do so, I have registered it in the collectionView but where it wont crash but nothing displays. Maybe this isn't the best way to do it - but what would be a good alternative to implement a spaced out horizontal scrolling and vertical scrolling? Here is my source code so far
import UIKit
class DiscoverViewController: UIViewController {
#IBOutlet weak var discoverTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
}
extension DiscoverViewController: UICollectionViewDelegate, UICollectionViewDataSource, UITableViewDelegate, UITableViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
collectionView.register(UINib(nibName: "DiscoverCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "DiscoverCollectionViewCell")
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "DiscoverCollectionViewCell", for: indexPath) as! DiscoverCollectionViewCell
cell.authorLabel.text = "this"
cell.coverImage.image = #imageLiteral(resourceName: "discover")
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = discoverTableView.dequeueReusableCell(withIdentifier: "CategoryTableViewCell", for: indexPath) as! CategoryTableViewCell
return cell
}
}
figured it out, the delegate and datasource had to be set to the TableView cell file as well as registering the xib on the TV with an instance of the CV on there. thanks to #Daniel for a point in the right direction.
I am trying to modify the size of the cells that the UICollectionview contains. I believe that the sizeForItemAtIndexPath should do the trick. Yet nothing is happening.
I have looked into similar questions, they have advised doing the same thing. I am sort of suspicious of my inheritance.
The problem is that the cells remain in the same size regardless of the value they were fed in.
class HikeViewController: UIViewController {
var test: Int?
#IBOutlet weak var options: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.prefersLargeTitles = false
print(test!)
options.dataSource = self
options.delegate = self
}
}
extension HikeViewController: UICollectionViewDelegate, UICollectionViewDataSource {
//collectionCell
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 2
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
var cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath as IndexPath)
cell.backgroundColor = UIColor.green
return cell
}
func collectionView(collectionView : UICollectionView,layout collectionViewLayout:UICollectionViewLayout,sizeForItemAtIndexPath indexPath:NSIndexPath) -> CGSize
{
return CGSize(width: 400, height: 500)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print(indexPath.row)
}
}
And when I conform to UICollectionViewDelegateFlowLayoutthe app termainates where I set the followings:
options.dataSource = self
options.delegate = self
And the error is:
Could not cast value of type 'HikingClub.HikeViewController' (0x108e1f948) to 'UICollectionViewDataSource' (0x10e723ff0).
It's worth adding that I have made sure of the connection between HikeViewController and the storyboard.
extension HikeViewController: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
}
It should be something like this
Make your extension a subclass of UICollectionViewDelegateFlowLayout
Use the following function
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// code
}
You need to specify that you implement the protocol UICollectionViewDelegateFlowLayout in your class declaration.
extension HikeViewController: UICollectionViewDelegateFlowLayout {}
also you have are not calling the delegate method, just defining a new one.
check the first parameter (collectionView -> _ collectionView)
func collectionView(_ collectionView : UICollectionView,layout collectionViewLayout:UICollec
In my app, I am using an UICollectionView. Now I want to develop an UIAlertController, when clicking onto any cell of the collection view.
I started with following code:
extension HomeViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
…
}
// specify cells
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
….
}
// called when widget is moved
func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
…
}
// called when clicked
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
print("Got clicked!")
}
}
But somehow, "Got clicked!" is never printed.
try next:
extension HomeViewController: UICollectionViewDataSource, UICollectionViewDelegate {
}
or
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
...
cell.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tap(_:))))
}
func tap(_ sender: UITapGestureRecognizer) {
let location = sender.location(in: self.collectionView)
let indexPath = self.collectionView.indexPathForItem(at: location)
if let index = indexPath {
print("Got clicked on index: \(index)!")
}
}
This is the version using the delegate:
extension HomeViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("item at \(indexPath.section)/\(indexPath.item) tapped")
}
}
Instead of using the extension you can also just add UICollectionViewDelegate and the collectionView(...didSelectItemAt:...) function to the class HomeViewController directly:
class HomeViewController: UICollectionViewDataSource, UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("item at \(indexPath.section)/\(indexPath.item) tapped")
}
}
This is because you might have placed some UIButton in the cell. Tap on some empty area in the cell then you will get the 'Got click on index'
I have a UICollectionView (let name aCollection) inside a View controller and i use a UICollectionReusableView to show header at the top of collection view
I also have a another UICollectionView (let name bCollection) in UICollectionReusableView. I need to show here top user list. but when i am trying to connect an outlet from storyboard i am getting an error
I know how to reload data in collection view
self.aCollection.reloadData()
My issue is how to connect bCollection outlet and how to reload bCollection to show user list coming from web services?
To take the outlet of bCollection, you need to create a subclass of UICollectionReusableView.
Example:
UIViewController containing aCollection:
class ViewController: UIViewController, UICollectionViewDataSource
{
#IBOutlet weak var aCollectionView: UICollectionView!
override func viewDidLoad()
{
super.viewDidLoad()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
return collectionView.dequeueReusableCell(withReuseIdentifier: "aCell", for: indexPath)
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView
{
return (collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "reusableView", for: indexPath) as! ReusableView)
}
}
UICollectionReusableView containing bCollection:
class ReusableView: UICollectionReusableView, UICollectionViewDataSource
{
#IBOutlet weak var bCollectionView: UICollectionView!
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
return collectionView.dequeueReusableCell(withReuseIdentifier: "bCell", for: indexPath)
}
}
Interface Screenshot
Edit:
To reload bCollection:
You need a reference to the reusableView that you are using. The way you are using it ReusableView() is not right.
Use it like this:
var reusableView: ReusableView?
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView
{
self.reusableView = (collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "reusableView", for: indexPath) as! ReusableView) //Storing the reference to reusableView
return self.reusableView!
}
Now, to reload bCollection,
self.reusableView?.bCollectionView.reloadData()
Since your UICollectionView (bCollection) is inside the UICollectionReusableView you can connect outlet to UICollectionReusableView's class only. So I believe you may have to create a custom class for UICollectionReusableView and assign it in the storyboard and connect bCollection 's outlet to that custom class
I am getting this error in my code it says to "Make a symbolic breakpoint at UICollectionViewFlowLayoutBreakForInvalidSizes to catch this in the debugger." I am confused as to what it is actually asking here is the code in which I am thinking its asking it to be put in just not sure where?
import UIKit
// MARK: - CUSTOM SOCIAL CELL
class SocialCell:UICollectionViewCell {
/* Views */
#IBOutlet weak var socialIcon: UIImageView!
#IBOutlet weak var socialLabel: UILabel!
}
class SocialList: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
/* Views */
#IBOutlet weak var socialCollView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: - COLLECTION VIEW DELEGATES
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return socials.count //socialNames.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("SocialCell", forIndexPath: indexPath) as! SocialCell
cell.socialLabel.text = "\(socials[indexPath.row]["name"]!)"
cell.socialIcon.image = UIImage(named: "\(socials[indexPath.row]["name"]!)")
return cell
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSizeMake(view.frame.size.width/3.8, view.frame.size.width/3.8)
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
selectedSocial = "\(socials[indexPath.row]["link"]!)"
selectedName = "\(socials[indexPath.row]["name"]!)"
selectedColor = socialColors[indexPath.row]
navigationController?.popViewControllerAnimated(true)
}
}
You can systematically solve this by doing this:
Also, you should share your complete error, so that I can lead you to more specific issue. My thinking is that you have some sort of autoLayout issue in your UICollectionView
On the left of your project, click the Break Point navigator
Next click on the plus button on the bottom left and click Add Symbolic BreakPoint
Then you will be shown a popup. Add UICollectionViewFlowLayoutBreakForInvalidSizes in there like so
After this, just hit enter(on keyboard) and click anywhere
Run your code and see where the project stops
You can resolve this issue by setting 'Estimate size = Custom' of collectionView in size inspector.