I want one View Controller to have seven horizontal button scrolls. I've set up the first Collection View, and I repeated the exact process for a second Collection View directly underneath, but I keep getting Thread 1: SIGABRT error. My code for the functional Collection View is here:
class xyViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
var tableImages: [String] = ["1.png", "2.png", "3.png", "4.png", "5.png", "6.png"]
override func viewDidLoad() {
// Initialize the collection views, set the desired frames
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return tableImages.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell:xyCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! xyCollectionViewCell
cell.xyImgCell.image = UIImage(named: tableImages[indexPath.row])
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
println("cell \(indexPath.row) selected")
}
}
It works when I run this.
So when I add a second Collection View underneath, create a new View Controller file to IBOutlet the button's image and a new Collection View Cell file to add the following code, it crashes.
class bwViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
var bwTableImages: [String] = ["a", "PlasmaBlast.png", "b.png", "c.png", "d.png", "e.png", "f.png", "g.png", "h.png", "i.png", "j.png"]
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return bwTableImages.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell:bwCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("cell1", forIndexPath: indexPath) as! bwCollectionViewCell
cell.bwImgCell.image = UIImage(named: bwTableImages[indexPath.row])
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
println("cell \(indexPath.row) selected")
}
}
Here is a two-section version of the code you wrote. I'm not sure if it addresses the error you are seeing, but it's how you'd do multiple collection views on one page.
class xyViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
var tableImagesOne: [String] = ["1.png", "2.png", "3.png", "4.png", "5.png", "6.png", "7.png", "8.png"]
var tableImagesTwo: [String] = ["1.png", "2.png", "3.png", "4.png", "5.png"]
override func viewDidLoad() {
// Initialize the collection views, set the desired frames
}
func numberOfSectionsInCollectionView(_ collectionView: UICollectionView) -> Int {
return 2
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if section == 0 {
return tableImagesOne.count
}
else {
return tableImagesTwo.count
}
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let row = indexPath.row
let section = indexPath.section
let cell:xyCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! xyCollectionViewCell
if section == 0 {
cell.xyImgCell.image = UIImage(named: tableImagesOne[row])
}
else if section == 1 {
cell.xyImgCell.image = UIImage(named: tableImagesTwo[row])
}
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
println("cell \(indexPath.section) : \(indexPath.row) selected")
}
}
Related
I am created UICollectionView inside of UITableView ,populating array values in UItableview is working perfect, when trying to populate a array values into collectionView getting same values in collectionView of all the rows of tableView, I want to populate a zeroth index array in collectionview of zeroth row UItableview and so on
below I tried a sample,
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate,UICollectionViewDelegate,UICollectionViewDataSource{
let array = ["product 1","product 2","product 3","product4"]
let array1 = ["product id 1","product id 2","product id 3","product id 4"]
let array2 = [["product id 1","product id 2"],["product id 3","product id 4"],["product id 5","product id 6"],["product id 7","product id 8","product id 9","product id 10","product id 11"]] as [NSArray]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : TableViewCell = tableView.dequeueReusableCell(withIdentifier: "cells") as! TableViewCell
cell.tableviewlabel1.text = array[indexPath.row]
cell.tableviewlabel2.text = array1[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return array2.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell : CollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "collection", for: indexPath) as! CollectionViewCell
let rowValue : NSArray = array2[indexPath.row]
for i in 0..<rowValue.count {
cell.collectionviewlabel1.text = rowValue[i] as? String
}
return cell
}
For example ,I want a zeroth index of array2 values in collectionview of zeroth row of tableview, and first index values in collectionview of first row of tableview and so on.
First your array2 has to be like this :
let array2 = [["product id 1","product id 2"],["product id 3","product id 4"],["product id 5","product id 6"],["product id 7","product id 8","product id 9","product id 10","product id 11"]]
Don't use NSArray in Swift. you can write it as [String], [[String]].
Your ViewController will have only UITableViewDelegate and UITableViewDatasource methods:
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : TableViewCell = tableView.dequeueReusableCell(withIdentifier: "cells") as! TableViewCell
cell.tableviewlabel1.text = array[indexPath.row]
cell.tableviewlabel2.text = array1[indexPath.row]
cell.arrayForCollectionView = array2
return cell
}
}
Then in your TableViewCell:
class TableViewCell: UITableViewCell {
var arrayForCollectionView : [[String]]! {
didSet {
self.collectionView.reloadData
}
}
#IBOutlet weak var collectionView: UICollectionView!
}
extension TableViewCell : UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if (arrayForCollectionView != nil) {
return arrayForCollectionView.count
}
return 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell : CollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "collection", for: indexPath) as! CollectionViewCell
let rowValue = arrayForCollectionView[indexPath.row]
for i in 0..<rowValue.count {
cell.collectionviewlabel1.text = rowValue[i] as? String
}
return cell
}
}
Let me know if you are getting any issue.
Giving an example for that:
first tableView is inside ViewController
class ViewController: UIViewController {
//MARK:- IBOUTELTS
//MARK:-
#IBOutlet weak var tableView: UITableView!
//MARK:- VARIABLES
//MARK:-
override func viewDidLoad() {
super.viewDidLoad()
}
}
extension YourViewConroller: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
}
}
And Your CollectionView is inside TableViewCell
extension YourTableViewCell: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
}
}
And make different class for TableView and CollectionView:
class YourTableViewCell: UITableViewCell { // tableview cell
}
classYourCollectionViewCell: UICollectionViewCell { // collectionviewcell
}
In top of that image you can see some images and plus button I want to do like this in my app so i used collection view to get this view and everything works fine but i cant add cell to my dynamic collection view can some one help me to do this process
code in my view controller:
import UIKit
import Alamofire
import SwiftyJSON
import SDWebImage
import SwiftElegantDropdownMenu
class EditPendingViewController: UIViewController,UITableViewDelegate,UITableViewDataSource,UITextViewDelegate,UICollectionViewDelegate,UICollectionViewDataSource,UIImagePickerControllerDelegate,UINavigationControllerDelegate{
var pendingImageString:[String]!
#IBOutlet var editPendingCollectionvIEW: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return pendingImageString.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("editPendingCell", forIndexPath: indexPath) as!MypendindeditCollectionViewCell
let img:NSString = pendingImageString[indexPath.item]
cell.editImage.sd_setImageWithURL(NSURL(string: imageApikey + (img as String)))
cell.contentView.layer.borderColor = UIColor.lightGrayColor().CGColor
cell.contentView.layer.borderWidth = 1.0
return cell
}
}
I have not done any process for adding cell to my collection view i just loaded the data from the server.now help to add the cell
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return pendingImageString.count + 1 // + 1 for last cell
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell : CollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! CollectionViewCell
cell.btn.tag = indexPath.row
if indexPath.item = pendingImageString.count {
cell.imageview = //your static image that is shown in last cell
cell.cancelButton.isHidden = true
}
else{
let img:NSString = pendingImageString[indexPath.item]
cell.editImage.sd_setImageWithURL(NSURL(string: imageApikey + (img as String)))
cell.cancelButton.isHidden = false
}
}
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
if indexPath.item = pendingImageString.count{
// update your array with new image file
}
}
// cancel button action
func buttonClicked(sender: UIButton?) {
let tag = sender.tag
// remove object from array and reload collectionview
}
On click of last cell of the collection view add logic to enter your product in the database then just reload the collection view
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if indexPath.row == pendingImageString.count - 1
{
//TODO - add item to database and reload collectionview
}
}
I have TableView and inside TableViewCell I have added UICollectionView. Now when user taps on any UICollectionView, I want to pass the data to next viewController but unfortunately I cannot use perform segue inside UITableViewCell class where I have didselect item. Is there any way to perform segue over here ?
Whole Code
class UserLibraryViewController: UIViewController {
extension UserLibraryViewController : UITableViewDelegate { }
extension UserLibraryViewController : UITableViewDataSource {
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return myBooksGenre[section]
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return myBooksGenre.count
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("userBooksTableViewCell") as! UserLibraryTableViewCell
cell.tableIndexPath = indexPath
return cell
}
}
TableViewCell
class UserLibraryTableViewCell: UITableViewCell {
#IBOutlet weak var collectionView: UICollectionView!
var tableIndexPath: NSIndexPath?
}
extension UserLibraryTableViewCell : UICollectionViewDataSource {
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 12
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("userBooksCollectionViewCell", forIndexPath: indexPath) as! UserLibraryCollectionViewCell
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
print("\(self.tableIndexPath!.section) ---- \(indexPath.item) \(tableSectionHeader[self.tableIndexPath!.section]) ")
}
}
extension UserLibraryTableViewCell : UICollectionViewDelegateFlowLayout {
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let itemsPerRow:CGFloat = 4
let hardCodedPadding:CGFloat = 5
let itemWidth = (collectionView.bounds.width / itemsPerRow) - hardCodedPadding
let itemHeight = collectionView.bounds.height - (2 * hardCodedPadding)
return CGSize(width: itemWidth, height: itemHeight)
}
}
Create one protocol, after that create its instance inside TableViewCell and implement the protocol in the UserLibraryViewController, after that in the didSelectItemAtIndexPath of CollectionView use that delegate instance to call the method like this.
protocol CustomCollectionDelegate {
func selectedCollectionCell(indexPath: NSIndexPath)
}
class UserLibraryTableViewCell: UITableViewCell {
#IBOutlet weak var collectionView: UICollectionView!
var tableIndexPath: NSIndexPath?
var delegate: CustomCollectionDelegate?
}
Now call this method inside your didSelectItemAtIndexPath of CollectionView.
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
print("\(self.tableIndexPath!.section) ---- \(indexPath.item) \(tableSectionHeader[self.tableIndexPath!.section]) ")
self.delegate?.selectedCollectionCell(indexPath)
}
Now implement this protocol in UserLibraryViewController like this and set delegate in the cellForRowAtIndexPath.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("userBooksTableViewCell") as! UserLibraryTableViewCell
cell.tableIndexPath = indexPath
cell.delegate = self
return cell
}
extension UserLibraryViewController : CustomCollectionDelegate {
func selectedCollectionCell(indexPath: NSIndexPath) {
self.performSegueWithIdentifier("Identifier", sender: indexPath)
}
}
Note: I have added protocol method with NSIndexPath as parameter you can change it with your custom object or with Dictionary/Array.
I have a reusable collection view cell. I am trying to set an image at didselect at index path but when i select a cell it return more than cell returning same image.
Here is the code.
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int{
return 1
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! CollectionViewCell
cell.userImage.layer.cornerRadius = cell.userImage.frame.size.width/2
cell.userImage.clipsToBounds = true
return cell
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int{
return 10
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath){
let cell = collectionView.cellForItemAtIndexPath(indexPath) as! CollectionViewCell
cell.userStatusImage.image = UIImage(named: "selectedcontact.png")
collectionView.reloadData()
}
You need to keep track of the selected cells.
var selectedIndexes = [Int]()
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 100
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath)
if self.selectedIndexes.contains(indexPath.row){
cell.backgroundColor = UIColor.redColor()
}
else{
cell.backgroundColor = UIColor.whiteColor()
}
return cell
}
// MARK: UICollectionViewDelegate
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
if selectedIndexes.contains(indexPath.row){
selectedIndexes.removeObject(indexPath.row)
}
else{
selectedIndexes.append(indexPath.row)
}
collectionView.reloadData()
}
Swift array don't have method to removeObject. Here is an extension for that
extension Array {
mutating func removeObject<U: Equatable>(object: U) -> Bool {
for (idx, objectToCompare) in self.enumerate() {
if let to = objectToCompare as? U {
if object == to {
self.removeAtIndex(idx)
return true
}
}
}
return false
}
}
It seems the last line of code collectionView.reloadData() will reload all the cell to initial status since you don't have any place checking whether one specific cell is selected or not.
I am trying to set up UICollectionView in my view controller. I am created custom cell CVCell.xib. My collection view is not showing up at all. What's missing in my code?
In my viewController.swift file:
#IBOutlet var collectionViewNew: UICollectionView?
override func viewDidLoad() {
super.viewDidLoad()
self.collectionViewNew?.registerNib(UINib(nibName: "CVCell", bundle: nil), forCellWithReuseIdentifier: "CVCell")
}
func numberOfSectionsInCollectionView(
collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return 6
}
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("CVCell", forIndexPath: indexPath) as CVCell
cell.backgroundColor = UIColor.orangeColor()
return cell
}