I have tried this numerous ways but I am unable to get it to work. I am trying to add a simple image and two text labels to a collection view cell and when the build completes the tableview is just blank. I am brand new too SWIFT but I am pretty sure I am missing something simple. What am I doing wrong?
ViewController
import UIKit
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate{
let locationName = ["Hawaii Resort", "Mountain Expedition", "Scuba Diving"]
let locationImage = [UIImage(named: "img0"), UIImage(named: "img1"), UIImage(named: "img2")]
let locationDescription = ["Lorem Ipsum 0", "Lorem Ipsum 1", "Lorem Ipsum 2"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return locationName.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
cell.locationName.text = locationName[indexPath.row]
cell.locationImage.image = locationImage[indexPath.row]
cell.locationDescription.text = locationDescription[indexPath.row]
return cell
}
}
CollectionViewCell
import UIKit
class CollectionViewCell: UICollectionViewCell {
#IBOutlet weak var locationImage: UIImageView!
#IBOutlet weak var locationName: UILabel!
#IBOutlet weak var locationDescription: UILabel!
}
You need to connect the collectionView to the ViewController.
Beneath locationDescription add:
#IBOutlet weak var collectionView: UICollectionView!
Then connect it on the storyboard.
Then within the viewDidLoad,set the delegate and data source to self
self.collectionView.delegate = self
self.collectionView.datasource = self
Related
The code below is my test files for my final project that will look like this. As you can see I will be scrolling by rows of one or two.
I have figured out how to get the horizontal scroll to work, however, it only displays two out of the six buttons as shown here in the simulator. As You can tell, it just repeats itself. I am needing the app to show app six buttons respectively.
The code for this:
var multiButton = [String]()
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
var multiButton = ["faceButton", "faceButtonTwo", "faceButtonThree", "faceButtonFour", "faceButtonFive", "faceButtonSix"]
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return multiButton.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell=collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! MyCollectionViewCell
// cell.multiButton.layer.cornerRadius=50.0
return cell
// cell.myWebSeriesImage.image=UIImage(named: webSeriesImages[indexPath.row])
// return cell
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
I have a separate file with all my IBOutlets as shown in this code:
import UIKit
class MyCollectionViewCell: UICollectionViewCell {
// var multiButton = ["faceButton", "faceButtonTwo", "faceButtonThree", "faceButtonFour", "faceButtonFive", "faceButtonSix"]
#IBOutlet weak var faceButtonFour: UIButton!
#IBOutlet weak var faceButtonFive: UIButton!
#IBOutlet weak var faceButtonThree: UIButton!
#IBOutlet weak var faceButtonTwo: UIButton!
#IBOutlet weak var faceButton: UIButton!
#IBOutlet weak var faceButtonSix: UIButton!
I have double checked the Identifiers, classes (class for cells are set for "myCollectionViewCell", which is the same file all IBOutlets are in), made sure all UIButtons were Installed, and have tried to find any abnormalities in the Attributes and Identity Inspector.
I also would like to address the issue of not being able to scroll horizontal without clicking outside the button.
UPDATE for Post:
This is what we are seeing currently after a previous comment to resize the collectionview. It continues to repeat over and over and I am struggling to find the reasons in my code.
This is a screenshot of main.storyboard.
This is very basic. You need to create something like this:
First create a collectionView with required height (50 for example) and add a button inside its cell. Give any width or height to the button (maybe 80 x 30) and add leading, trailing, top and bottom constraints. Make sure to change scroll direction to horizontal as required by you.
After that create a collectionView class and connect your button outlet to it:
import UIKit
class ButtonCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var button: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
}
}
In your main ViewController, connect collectionView and add delegate & datasource function:
import UIKit
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var collectionViewButtons: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
collectionViewButtons.delegate = self
collectionViewButtons.dataSource = self
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 6 //number of buttons
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! ButtonCollectionViewCell
cell.button.setTitle("Button\(indexPath.item)", for: .normal) //set button title
if indexPath.item == 0 { //first button
cell.button.backgroundColor = UIColor.purple //set button background
}
else if indexPath.item == 1 { //second button
cell.button.backgroundColor = UIColor.red
}
else if indexPath.item == 2 { //3rd button
cell.button.backgroundColor = UIColor.systemGreen
}
else { // for remaining buttons
cell.button.backgroundColor = UIColor.darkGray
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if indexPath.item == 0 { // opens any page by clicking button 1
let vc = storyboard?.instantiateViewController(withIdentifier: "anyVC1") as! ViewController1
navigationController?.pushViewController(vc, animated: true)
}
else if indexPath.item == 1 {
let vc = storyboard?.instantiateViewController(withIdentifier: "anyVC2") as! ViewController2
navigationController?.pushViewController(vc, animated: true)
}
else if indexPath.item == 2 {
let vc = storyboard?.instantiateViewController(withIdentifier: "anyVC3") as! ViewController3
navigationController?.pushViewController(vc, animated: true)
}
else {
let vc = storyboard?.instantiateViewController(withIdentifier: "anyVC4") as! ViewController4
navigationController?.pushViewController(vc, animated: true)
}
}
}
You can return any number of buttons by changing return 6 to any required number or use any array which can further be used to set properties of buttons created.
The didSelectAnItem can be used to add functionality when a cell is tapped.
In the end you should get output like this where you can scroll horizontally to see remaining buttons:
This question already has answers here:
unrecognized selector sent to instance 0x8c9a6d0
(4 answers)
Closed 3 years ago.
I'm currently studying swift CollectionView, I followed each step of the tutorial but somehow my app ends up being terminated with this error
Disconnect the dateSource and delegate seems can stop it from crashing but it ends up having nothing in the collection view. Any hints would be appreciated:)
this is my ViewController:
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
struct Item {
var title:String
var Image:String
var price:Double
}
let items:[Item] = [Item(title: "Mario Kart", Image: "Mario", price: 5), Item(title: "Car", Image: "Car", price: 6), Item(title: "Doll", Image: "Doll", price: 3)]
override func viewDidLoad() {
super.viewDidLoad()
}
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! CollectionViewCell
cell.myImage.image = UIImage(named: items[indexPath.row].Image)
cell.myPrice.text = String(items[indexPath.row].price)
cell.myTitle.text = String(items[indexPath.row].title)
return cell
}
}
class CollectionViewCell: UICollectionViewCell {
#IBOutlet weak var myImage: UIImageView!
#IBOutlet weak var myPrice: UILabel!
#IBOutlet weak var myTitle: UILabel!
}
Please make an IBOutlet connection to collectionView.
Then add the
collectionView.delegate=self
collectionView.datasource=self
lines inside viewDidLoad method.
Wanting to store a users selected collection cell title as a local variable, so then it can be passed along to the next view using a segue. I'm having trouble with the didSelectItemAt function, even if I put a print statement there, nothing happens when a cell is selected.
GoalsViewController
import Foundation
import UIKit
class GoalsViewController: UIViewController {
#IBOutlet weak var collectionView: UICollectionView!
var selectedGoal: String = ""
var goalArray = ["Goal 1", "Goal 2"]
var imageArray = ["1", "2"]
override func viewDidLoad() {
super.viewDidLoad()
collectionView.dataSource = self
collectionView.delegate = self
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToGoalDetail" {
let secondVC = segue.destination as! GoalDetailViewController
secondVC.goalSelectedOnHome = selectedGoal
}
}
}
extension GoalsViewController: UICollectionViewDataSource, UICollectionViewDelegate {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return goalArray.count
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedGoal = goalArray[indexPath.row]
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "GoalCell", for: indexPath) as! GoalsCollectionViewCell
cell.goalTitleLabel.text = goalArray[indexPath.row]
cell.backgroundColor = UIColor.darkGray
cell.featuredImageView.image = UIImage(named: "\(imageArray[indexPath.row])")
return cell
}
}
GoalsCollectionViewCell
import UIKit
class GoalsCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var featuredImageView: UIImageView!
#IBOutlet weak var goalTitleLabel: UILabel!
#IBOutlet weak var backgroundColorView: UIView!
}
GoalsDetailViewController
import UIKit
class GoalDetailViewController: UIViewController {
#IBOutlet weak var closeButtonImage: UIImageView!
#IBOutlet weak var goalDetailTitle: UILabel!
#IBOutlet weak var closeButton: UIButton!
var goalSelectedOnHome = ""
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
goalDetailTitle.text = goalSelectedOnHome
closeButton.setImage(UIImage(named: "closeIcon"), for: .normal)
closeButton.addTarget(self, action: #selector(closeButtonTapped), for: .touchUpInside)
}
#objc func closeButtonTapped(sender:UIButton!) {
self.dismiss(animated: true, completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I trying to add pageControl in viewController for display current page and total pages.
I have collectionView inside viewController. But if i add #IBOutlet in viewController i get the error:
"The pageControl outlet from the DetailViewController to the UIPageControl is invalid. Outlet cannot be connected to repeating content."
That means repeating content?
I understand that this question has been asked many times, but I tried what was suggested but nothing helped.
PageControl in main.storyboard have only one #IBOutlet and it throws an error...
If need my code, he is here:
class DetailViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UITableViewDelegate, UITableViewDataSource {
// MARK: - IBOutlet's
#IBOutlet weak var collectionView: UICollectionView!
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var pageControl: UIPageControl!
var hallImages: Hall?
var currentPage = 0
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
tableView.estimatedRowHeight = 626
tableView.rowHeight = UITableViewAutomaticDimension
}
// MARK: - CollectionView
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
guard let imagesHall = hallImages?.ImagesHalls.count else {
return 0
}
return imagesHall
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! DetailCollectionViewCell
if let imagesHalls = hallImages?.ImagesHalls[indexPath.item] {
cell.imageView.sd_setImage(with: URL(string: imagesHalls))
}
return cell
}
}
How i can add pageControll in collectionView or collectionCell (i don't know how is better)?
I had the same problem. It is because your page control is a subview of the cell. You cannot do this.
take it out of your cell
put it in your main view/ safe area
Trying to add a cell to my ViewController, and I'm having trouble. I'm wondering if I have all my delegates. Currently, I can change the color of the collection view's background, but can't add any cells.
I'm using an array of text from my Listing() object to drive the collection view cells. On viewDidLoad the length is 4. I envisioned using this count for the numberofItemsInSection, however, if I put the print statement there it is never printed. Which makes me think the wrong delegate is called and the method is never hit. Correct?
import UIKit
class ListingDetailViewController: UIViewController,
UICollectionViewDelegateFlowLayout {
var listing = Listing()
// #IBOutlet var image: UIImageView!
#IBOutlet var post: UITextView!
#IBOutlet var price: UILabel!
#IBOutlet var amenitiesCollection: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
navigationItem.title = listing.title
self.amenitiesCollection!.backgroundColor = UIColor.gray
print(listing.amenities.count)//printed 4
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int{
print(listing.amenities.count)
return listing.amenities.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let identifier = "UICollectionViewCell"
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath)
return cell
}
}
Make sure you have linked the CollectionView delegate and datasource to your view controller.
In viewDidLoad() add:
self.amenitiesCollection.delegate = self
self.amenitiesCollection.dataSource = self
==================================
EDIT:
If you have already linked the delegate and dataSource, try reloading the collection view in viewDidAppear(_:)
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.amenitiesCollection.reloadData()
}