I am currently trying to control two different collection view. I have also embedded buttons in each of the collection views I want to make each of them contain a set of values from an array. This is my code so far, I don't know what I should actually do to achieve that:
import UIKit
class MyButtonCell: UICollectionViewCell{
#IBOutlet weak var buttonOne: UIButton!
#IBOutlet weak var targetButton: UIButton!
var callback: (() -> ())?
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() -> Void {
contentView.layer.borderWidth = 1
contentView.layer.borderColor = UIColor.black.cgColor
}
#IBAction func buttonTapped(_ sender: UIButton) {
callback?()
}
}
class StevenViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
let buttonTitles: [String] = [
"4", "6", "7", "8"
]
var targetButtonTitles: [String] = [
"", "", "", ""
]
var current:String = ""
#IBOutlet var collectionView: UICollectionView!
#IBOutlet var targetCollection: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
targetCollection.delegate = self
targetCollection.dataSource = self
collectionView.delegate = self
collectionView.dataSource = self
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return buttonTitles.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "myCellID", for: indexPath) as! MyButtonCell
let targetCell = targetCollection.dequeueReusableCell(withReuseIdentifier: "myCellID", for: indexPath) as! MyButtonCell
// set the button title (and any other properties)
cell.buttonOne.setTitle(buttonTitles[indexPath.item], for: [])
targetCell.targetButton.setTitle(self.targetButtonTitles[indexPath.item], for: [])
// set the cell's callback closure
cell.callback = {
print("Button was tapped at \(indexPath)")
self.targetButtonTitles.append(self.buttonTitles[indexPath.item])
print(self.targetButtonTitles)
// do what you want when the button is tapped
}
return targetCell
}
}
buttonTitles and targetButtonTitles are the two arrays I want each of my collectionviews to contain.
This is what it looks like right now - both are showing the same array. I understand that I probably should have different identifier ID for the cells, but once I do that, it gave me an error saying "could not dequeue a view of kind: UICollectionElementKindCell with identifier target"
In UICollectionViewDelegate & UICollectionViewDataSource
You can use this code snippet to identify the current UICollectionView.
if collectionView == [YOUR_COLLECTIONVIEW_QUTLET] {
}
Related
I current have a collectionview attached to a array of strings. I want to align these cells center regardless of the number of things in the array. I am not sure how to do it, and where to do it.
import UIKit
class MyButtonCell: UICollectionViewCell{
#IBOutlet weak var buttonOne: UIButton!
#IBOutlet weak var targetButton: UIButton!
var callback: (() -> ())?
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() -> Void {
contentView.layer.borderWidth = 1
contentView.layer.borderColor = UIColor.black.cgColor
}
#IBAction func buttonTapped(_ sender: UIButton) {
callback?()
}
}
class StevenViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
let buttonTitles: [String] = [
"4", "6", "7", "8"
]
var targetButtonTitles: [String] = [
"", "", "", ""
]
var current:String = ""
#IBOutlet var collectionView: UICollectionView!
#IBOutlet var targetCollection: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
targetCollection.delegate = self
targetCollection.dataSource = self
collectionView.delegate = self
collectionView.dataSource = self
collectionView.tag = 1
targetCollection.tag = 2
}
func centerItemsInCollectionView(cellWidth: Double, numberOfItems: Double, spaceBetweenCell: Double, collectionView: UICollectionView) -> UIEdgeInsets {
let totalWidth = cellWidth * numberOfItems
let totalSpacingWidth = spaceBetweenCell * (numberOfItems - 1)
let leftInset = (collectionView.frame.width - CGFloat(totalWidth + totalSpacingWidth)) / 2
let rightInset = leftInset
return UIEdgeInsets(top: 0, left: leftInset, bottom: 0, right: rightInset)
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView.tag == 1 {
return buttonTitles.count
} else {
return targetButtonTitles.count
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// set the button title (and any other properties)
if collectionView.tag == 1 {
// Setup here your cell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "myCellID", for: indexPath) as! MyButtonCell
cell.callback = {
print("Button was tapped at \(indexPath)")
self.targetButtonTitles[indexPath.item] = self.buttonTitles[indexPath.item]
//print(self.targetButtonTitles)
self.current = self.buttonTitles[indexPath.item]
print(self.current)
//collectionView.reloadData()
// do what you want when the button is tapped
}
cell.buttonOne.setTitle(buttonTitles[indexPath.item], for: [])
return cell
} else {
// Setup here your targetCell
let targetCell = targetCollection.dequeueReusableCell(withReuseIdentifier: "myCellID", for: indexPath) as! MyButtonCell
targetCell.callback = {
if self.current != ""{
self.targetButtonTitles[indexPath.item] = self.current
print(self.targetButtonTitles)
targetCell.targetButton.setTitle(self.targetButtonTitles[indexPath.item], for: [])
self.current = ""
}else{
self.targetButtonTitles[indexPath.item] = ""
targetCell.targetButton.setTitle(self.targetButtonTitles[indexPath.item], for: [])
}
}
return targetCell
}
}
}
As you can see, right now they are just starting from the left. So, How should I align them in the middle.
// I just want to filter array list which is shown in collection view cell when user enter text in the textfield.
On textfield editing collection data will be sort and filter according to textfield input. In case of collection view has a data about states, If I input 'A' in textfield, all collection data will be sort and display all state names starting with alphabet 'A'. Please tell me logic for this.
ios iphone
here is the link of my project ---- https://drive.google.com/drive/folders/1d56PWO2j6YcDU2AJyCseZC16dfUeV7Bd?usp=sharing //
ViewController.swift
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
if let customView = Bundle.main.loadNibNamed("CustomView", owner: self, options: nil)?.first as? CustomView {
self.textField.inputAccessoryView = customView
}
}
}
class CustomView: UIView, UICollectionViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
let words = ["abscind","downwind","headwind","lind","rescind","sind","skinned","tailwind","thin-skinned","tinned","twinned","upwind","whirlwind","wind"]
override func awakeFromNib() {
super.awakeFromNib()
self.collectionView.register(UINib(nibName: "CustomCell", bundle: nil), forCellWithReuseIdentifier: "cell")
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.words.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CustomCell
cell.label.text = self.words[indexPath.row]
return cell
}
}
class CustomCell: UICollectionViewCell {
#IBOutlet weak var label: UILabel!
}
Create another array filteredWords in CustomView class and use that array in collection view datasource methods
class CustomView: UIView, UICollectionViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
let words = ["abscind","downwind","headwind","lind","rescind","sind","skinned","tailwind","thin-skinned","tinned","twinned","upwind","whirlwind","wind"]
var filteredWords = [String]()
override func awakeFromNib() {
super.awakeFromNib()
filteredWords = words
self.collectionView.register(UINib(nibName: "CustomCell", bundle: nil), forCellWithReuseIdentifier: "cell")
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.filteredWords.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CustomCell
cell.label.text = self.filteredWords[indexPath.row]
return cell
}
}
In ViewController add target to textField for .editingChanged.
Then filter, sort the array and reload the collectionView.
class ViewController: UIViewController {
#IBOutlet weak var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
if let customView = Bundle.main.loadNibNamed("CustomView", owner: self, options: nil)?.first as? CustomView {
self.textField.inputAccessoryView = customView
self.textField.addTarget(self, action: #selector(textChanged(_:)), for: .editingChanged)
}
}
#objc func textChanged(_ sender: UITextField) {
if let customView = textField.inputAccessoryView as? CustomView {
if textField.text!.isEmpty {
customView.filteredWords = customView.words
customView.collectionView.reloadData()
} else {
customView.filteredWords = customView.words
.filter({ $0.localizedCaseInsensitiveContains(textField.text!) }).sorted(by: {
if let range0 = $0.range(of: textField.text!, options: [.caseInsensitive], range: $0.startIndex..<$0.endIndex, locale: nil),
let range1 = $1.range(of: textField.text!, options: [.caseInsensitive], range: $1.startIndex..<$1.endIndex, locale: nil) {
return range0.lowerBound < range1.lowerBound
} else {
return false
}
})
customView.collectionView.reloadData()
}
}
}
}
The sorted array will be sorted based on the index of searched text. Ex. for text "in" the filtered and sorted result will be
["lind", "sind", "tinned", "wind", "skinned", "thin-skinned",
"twinned", "upwind", "abscind", "rescind", "downwind", "headwind",
"tailwind", "whirlwind"]
You need to update your dataSource everytime there is a change in textField's text.
You can track the changes in textField's text using UITextFieldDelegate method - textField(_:shouldChangeCharactersIn:replacementString:)
I've taken 2 arrays:
1. arr: It will contain the whole content that you can show in collectionView
2. dataSourceArr: It will contain the filtered content from arr based on textField's text. Initially both the arrays will have same content.
class ViewController: UIViewController, UICollectionViewDataSource, UITextFieldDelegate {
#IBOutlet weak var collectionView: UICollectionView!
var arr = [String]() //Original Array
var dataSourceArr = arr //Filtered array based on textField content
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return dataSourceArr.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
return cell
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
self.reload(textField)
return true
}
func reload(_ textField: UITextField) {
if let text = textField.text {
dataSourceArr = self.arr.filter({ $0.hasPrefix(text) }).sorted()
collectionView.reloadData()
}
}
}
You should not suppose to ask question like this, you should also provide the code that you have tried
let array = ["Alabama", "Alaska", "Arizona", "Arkansas", "Aalborg", "Indiana", "New Jersey"]
let searchtext = "A"
let filterArray = array.filter({ $0.hasPrefix(searchtext) }).sorted()
I have a custom xib file which contains a label and a UICollectionView. I have a second xib file for the collection view's cell with a custom subclass of UICollectionViewCell.
The parent xib file's owner looks like below-
import UIKit
class PackageSizePickerVC: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
#IBOutlet weak var collection: UICollectionView!
let sizes: [PackageSize] = {
let small = PackageSize(title: "Small", imageName: "S")
let medium = PackageSize(title: "Medium", imageName: "M")
let large = PackageSize(title: "Large", imageName: "L")
let extralarge = PackageSize(title: "Extra Large", imageName: "XL")
return [small, medium, large, extralarge]
}()
override func viewDidLoad() {
super.viewDidLoad()
collection.delegate = self
collection.dataSource = self
collection.register(UINib(nibName: "SizesCell", bundle: nil), forCellWithReuseIdentifier: "Sizecell") //register with nib
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return sizes.count
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.width, height: collectionView.frame.height)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collection.dequeueReusableCell(withReuseIdentifier: "Sizecell", for: indexPath) as? SizesCell {
let size = sizes[indexPath.row]
cell.image = size.imageName
cell.title = size.title
return cell
}else{
return UICollectionViewCell()
}
}
}
The UICollectionViewCell xib file is named SizesCell.xib and the class file is SizesCell.swift, the code in SizesCell class looks like this-
import UIKit
class SizesCell: UICollectionViewCell {
#IBOutlet weak var sizeImage: UIImageView!
#IBOutlet weak var sizeLabel: UILabel!
var image: String!
var title: String!
override init(frame: CGRect) {
super.init(frame: frame)
sizeImage.image = UIImage(named: image)
sizeLabel.text = title
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Where PackageSize is a Struct as
struct PackageSize {
let title: String
let imageName: String
}
Now the problem I am facing is that the cells simply won't load into the collection view in the parent xib file and I simply can't figure out why the init in the UICollectionViewCell class is not being called at all. I have tried it with awakeFromNib() as well, but that didn't work either. The file owners, custom classes etc. are all set correctly in the IB. What am I missing here?
I want to instantiate a ViewController from a custom tableViewCell(conforming to UICollectionViewDelegate, UICollectionDatasource) class which has a custom CollectionView embedded in it.The segue needs to be performed when a particular section of the CollectionView is selected. Already tried using protocols doesnt work!
my custom TableView class :-
import UIKit
protocol transferDelegate{
func transfer(_: Int)
}
class ParentTableViewCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource{
#IBOutlet weak var parentCellHeader: UIView!
#IBOutlet weak var feedPostUsername: UILabel!
#IBOutlet weak var feedPostUserDetails: UILabel!
#IBOutlet weak var feedPostDescription: UILabel!
#IBOutlet weak var feedPicturesCollectionView: UICollectionView!
#IBOutlet weak var feedUserProfilePictures: CustomProfilepicture!
var transferingDelegate : transferDelegate?
override func awakeFromNib() {
super.awakeFromNib()
feedPicturesCollectionView.dataSource = self
feedPicturesCollectionView.delegate = self
feedPicturesCollectionView.pagingEnabled = true
feedPicturesCollectionView.backgroundColor = UIColor.clearColor()
}
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) ->
UICollectionViewCell {
let cell = feedPicturesCollectionView.dequeueReusableCellWithReuseIdentifier("FeedPicturesCell", forIndexPath: indexPath) as! FeedPhotosCell
switch(indexPath.row){
case 0 : cell.feedImages.image = UIImage(named: "defaultProfilePic")
case 1 : cell.feedImages.image = UIImage(named: "image1")
case 2 : cell.feedImages.image = UIImage(named: "image2")
case 3 : cell.feedImages.image = UIImage(named: "image3")
default : cell.feedImages.image = UIImage(named: "defaultProfilePic")
}
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
print(indexPath.row)
transferingDelegate?.transfer(indexPath.row)
}
}
my viewController class : -
import UIKit
class ViewController: UIViewController , UITableViewDelegate, UITableViewDataSource,transferDelegate{
var xibName : String = "HomepageFeedCellHeader"
var lords : [String] = ["name1","name2","name3"]
var que : [String] = ["--","red","blue"]
var desc : [String] = ["abcE","defn","ghi"]
var menProfilePictures : [UIImage] = [UIImage(named: "image1")!,UIImage(named: "image2")!,UIImage(named: "image3")!]
#IBOutlet weak var parentTableView: UITableView!
var a : ParentTableViewCell = ParentTableViewCell()
override func viewDidLoad() {
super.viewDidLoad()
parentTableView.delegate = self
parentTableView.dataSource = self
// Do any additional setup after loading the view, typically from a nib.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return lords.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = parentTableView.dequeueReusableCellWithIdentifier("ParentCell", forIndexPath: indexPath) as! ParentTableViewCell
a.transferingDelegate = self
cell.feedPostUsername.text = lords[indexPath.row]
cell.feedPostUserDetails.text = queens[indexPath.row]
cell.feedPostDescription.text = desc[indexPath.row]
cell.feedUserProfilePictures.image = menProfilePictures[indexPath.row]
return cell
}
func transfer(itemNo : Int) {
print("call recieved in viewController from item \(itemNo)")
}
}
Your didSelectItemAtIndexPath problem is solved. This is the answer of your second issue that you are mention in comment. You can not assign the image the imageView, if it is not in the navigation hierarchy. Your problem is that you detailImage is nil because this ViewController is not loaded in the window hierarchy. To solve your problem just do like this
imagePopOverScene?.selImage = menProfilePictures[itemNo]
Now declare selImage in your imagePopOverScene like this
var selImage: UIImage!
Also add follwing line in your viewDidLoad of imagePopOverSceneVC
self.detailImage.image = self.selImage
This will solve your problem
UPDATE: I solved my primary issue of correct images not loading until scrolling on the collectionView. I added a collectionView.reloadData() to the tableView:cellForRowAtIndexPath. I also made some changes to pre-load the sequence array, instead of building it while scrolling through the table (tableView:cellForRowAtIndexPath).
Added the updates to GitHub if you are interested.
https://github.com/Druiced/OpenDeck
I will follow-up once I figure out how to prevent the App from crashing when a dynamic value is placed in the return (if i set this to 15, the app will not crash):
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return count(Array(sequenceArray[collectionView.tag])) / 2
}
ORIGINAL POST:
request for some guidance.
This tutorial helped me realize this must have to do with my DataSource/Delegate. The author builds the cell with addSubview instead of taking advantage of the Xcode prototype cell, which seems like a cool thing, so I'm trying to do it.
http://ashfurrow.com/blog/putting-a-uicollectionview-in-a-uitableviewcell
Any criticism about my approach or failure to follow best practices is welcome.
Each cell in the table has a UICollectionView. Each cell in the Collection View displays an image in order of the saved "Sequence" string. example: "ADKDQDJDTD" link up to AD.png KD.png QD.png JD.png TD.png
I have two issues I can't seem to get past.
numberOfItemsInSection gets whacky when the number of cards is driven by the array length (return handArray.count / 2). If I place a fixed number the app will work, but not very slick.
When the table first comes up, the correct cards do not display until I scroll up and down the table. It also appears the data for each CollectionView is crossing paths as the wrong cards show up when scrolling up and down rapidly.
I'm almost positive this has to do with how my datasource is setup.
DeckTableViewController.swift
import UIKit
import Parse
var deviceID: String?
var noRefresh: Bool?
var sequenceArray: Array<Character>?
class DeckTableViewController: UITableViewController, UICollectionViewDelegate, UICollectionViewDataSource {
var handArray: Array<Character>!
var timeLineData:NSMutableArray = NSMutableArray()
override func viewDidLoad() {
super.viewDidLoad()
noRefresh = false
deviceId = UIDevice.currentDevice().identifierForVendor.UUIDString
}
override func viewDidAppear(animated: Bool) {
if noRefresh == false {
loadData()
noRefresh = true
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return timeLineData.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:DeckTableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! DeckTableViewCell
let deck:PFObject = timeLineData.objectAtIndex(indexPath.row) as! PFObject
cell.collectionView.dataSource = self
cell.collectionView.delegate = self
let sequenceTemp = deck.objectForKey("Sequence") as! String
handArray = Array(sequenceTemp)
cell.sequenceId.setTitle(deck.objectId, forState: UIControlState.Normal)
cell.cardCountLabel.text = "\((count(sequenceTemp)/2))"
// Date to String Stuff
var dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "(MM-dd) hh:mm:ss"
cell.timeLabel.text = dateFormatter.stringFromDate(deck.updatedAt!)
let layout:UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.itemSize = CGSizeMake(99, 140)
layout.scrollDirection = UICollectionViewScrollDirection.Horizontal
cell.collectionView.collectionViewLayout = layout
return cell
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return handArray.count / 2
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell:TableCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! TableCollectionViewCell
var bcolor : UIColor = UIColor.orangeColor()
cell.layer.borderColor = bcolor.CGColor
cell.layer.borderWidth = 2
cell.layer.cornerRadius = 3
var firstLetter: Character!
var secondLetter: Character!
//Building card file names from Sequence data
if (indexPath.row * 2) + 1 <= handArray.count {
firstLetter = handArray[indexPath.row * 2]
secondLetter = handArray[indexPath.row * 2 + 1]
let imageNameString = "\(firstLetter)\(secondLetter).png"
let front = UIImage(named: imageNameString)
cell.ImageView.backgroundColor = UIColor.orangeColor()
cell.ImageView.image = front
}
return cell
}
DeckTableViewCell.swift
import UIKit
class DeckTableViewCell: UITableViewCell, UITextViewDelegate {
#IBOutlet var collectionView: UICollectionView!
#IBOutlet var sequenceId: UIButton!
#IBOutlet var timeLabel: UILabel!
#IBOutlet var cardCountLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
TableCollectionViewCell.swift
import UIKit
class TableCollectionViewCell: UICollectionViewCell {
#IBOutlet var ImageView: UIImageView!
}
For this example I set (return handArray.count / 2) to a 10 and loaded 3 sequences.
The number in the top center represents the number of cards for each row.
Notice the CollectionView does not update with the right cards, it's picking up data from the other CollectionViews. IF I add bunch more sequences to this mix, when scrolling up and down, the correct cards WILL populate SOMETIMES, but unpredictable.
Thanks for any suggestions, I'm happy to go back to the drawing board. Cheers
Ok lets think this way, your DeckTableViewController acts as datasource for tableview, and DeckTableViewCell acts as datasource for collection view.
with the above thing in mind we create a sample project
i am not going in depth, i am giving example like the tutorial as u go through
lets create a sample project with single view app and in ViewController
past the below code, i took one array of integers which contains some values as how many cells to be appears in collection view. don't forget add tableview and set its datasource and deleagte.
before we are coding to controller class we need some classes like custom tableview cell and custom collection view cell we create them first
create a new file which is the subclass of UICollectionViewCell and name it as CustomCollectionViewCell and with xib file.
class CustomCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var aLabel: UILabel! //to show the card number
#IBOutlet weak var imageView: UIImageView! //imageview i am setting it's background color
override init(frame: CGRect) {
super.init(frame: frame)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func awakeFromNib() {
super.awakeFromNib()
}
}
and create a outlets for label and image view as in the above code.
Next, create new file subclass of UITableViewCell and name it as CustomTableViewCell with xib file. open up CustomTableViewCell.xib file and drag and drop the collection view and set it's datasource and delegate to cell not the controller.
and create a outlet for the collection view and name it as foldersCollectionView.
pass the below code
import UIKit
class CustomTableViewCell: UITableViewCell,UICollectionViewDataSource,UICollectionViewDelegate {
#IBOutlet weak var foldersCollectionView: UICollectionView!
override init(frame: CGRect) {
super.init(frame: frame)
}
required init(coder aDecoder: NSCoder) {
// fatalError("init(coder:) has not been implemented")
super.init(coder: aDecoder)
}
var folderCount:Int?
{
didSet(value)
{
}
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
//configure our collectionview
var aFlowLayout : UICollectionViewFlowLayout = UICollectionViewFlowLayout()
aFlowLayout.scrollDirection = UICollectionViewScrollDirection.Horizontal
aFlowLayout.itemSize = CGSizeMake(60.0, 90.0)
aFlowLayout.minimumLineSpacing = 10.0
aFlowLayout.minimumInteritemSpacing = 0.0
aFlowLayout.sectionInset = UIEdgeInsetsMake(2, 9, 0, 10)
foldersCollectionView.collectionViewLayout = aFlowLayout
foldersCollectionView.registerClass(CustomCollectionViewCell.self, forCellWithReuseIdentifier: "FOLDER_CELL")
var cNib:UINib? = UINib(nibName: "CustomCollectionViewCell", bundle: nil)
foldersCollectionView.registerNib(cNib, forCellWithReuseIdentifier: "FOLDER_CELL")
foldersCollectionView.frame = self.bounds
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
class func CreateCustomCell() -> CustomTableViewCell
{
var nibElements: Array = NSBundle.mainBundle().loadNibNamed("CustomTableViewCell", owner: self, options: nil)
var item: AnyObject?
for item in nibElements
{
if item is UITableViewCell
{
return item as CustomTableViewCell
}
}
return item as CustomTableViewCell
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
var cell :CustomCollectionViewCell? = collectionView.dequeueReusableCellWithReuseIdentifier("FOLDER_CELL", forIndexPath: indexPath) as? CustomCollectionViewCell
//hear u can modify which image to be displayed in the collection view cell
cell?.aLabel.text = "Card:\(indexPath.row)"
return cell!
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return folderCount!
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
}
now we are going the code the ViewController class
now just past the below code
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
var cardCountArray:[Int] = []
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
cardCountArray = [5,15,6,12,7,10]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return cardCountArray.count
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cell:CustomTableViewCell? = tableView.dequeueReusableCellWithIdentifier("CELL") as? CustomTableViewCell;
if(cell == nil)
{
cell = CustomTableViewCell.CreateCustomCell()
}
cell?.folderCount = cardCountArray[indexPath.section]
cell?.foldersCollectionView.reloadData()
cell?.clipsToBounds = true
return cell!;
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
return 100.0
}
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
var headerView:UIView = UIView(frame: CGRectMake(0, 0, tableView.bounds.size.width, 70.0))
var labelTitle:UILabel = UILabel(frame: CGRectMake(0, 0, tableView.bounds.size.width, 35))
var descriptionTitle:UILabel = UILabel(frame: CGRectMake(0, 20,tableView.bounds.size.width , 30))
headerView.addSubview(labelTitle)
headerView.addSubview(descriptionTitle)
labelTitle.text = "TOTAL_CARDS in section:\(section)"
descriptionTitle.text = "This CARD_SECTION contains \(cardCountArray[section]) CARDS"
return headerView
}
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50.0
}
}
result will be like below
if any thing missing please let me know
For your comment I have an array, for example, ["2C3C4C5C6C7C", "AD2D3D4D5D", "9H8H7H"]
for this u need to make below modification
//for first row u get like this
//the string for the row is 2C3C4C5C6C7C
//stringForCell = "2C3C4C5C6C7C"
//2C
//3C
//4C
//5C
//6C
//7C
//for other cells u can get like below
//the string for the row is AD2D3D4D5D
//stringForCell = "AD2D3D4D5D"
//AD
//2D
//3D
//4D
//5D
//the string for the row is 9H8H7H
//stringForCell = "9H8H7H"
//9H
//8H
//7H
//in controller controller class define array of string
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
var cardCountArray:[Int] = []
var stringArray : [String] = []
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
stringArray = ["2C3C4C5C6C7C", "AD2D3D4D5D", "9H8H7H"]
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
// return cardCountArray.count
return stringArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cell:CustomTableViewCell? = tableView.dequeueReusableCellWithIdentifier("CELL") as? CustomTableViewCell;
if(cell == nil)
{
cell = CustomTableViewCell.CreateCustomCell()
}
//cell?.folderCount = cardCountArray[indexPath.section]
cell?.stringForCell = stringArray[indexPath.section];
cell?.foldersCollectionView.reloadData()
cell?.clipsToBounds = true
return cell!;
}
//in custom tableview cell add a string variable
class CustomTableViewCell: UITableViewCell,UICollectionViewDataSource,UICollectionViewDelegate {
#IBOutlet weak var foldersCollectionView: UICollectionView!
var stringForCell:String = "" //add the string to hold the string
//rest of the code
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
var cell :CustomCollectionViewCell? = collectionView.dequeueReusableCellWithReuseIdentifier("FOLDER_CELL", forIndexPath: indexPath) as? CustomCollectionViewCell
var str:NSString = stringForCell
var length = str.length
var totalLlength:Int = length/2
var indexStart = indexPath.row * (2);
var aRange = NSMakeRange(indexStart, 2)
var cardString:NSString = str.substringWithRange(aRange)
println(cardString)
cell?.aLabel.text = "Card: \(cardString)"
return cell!
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
println("the string for the row is \(stringForCell)")
var str:NSString = stringForCell
var length:Int = str.length
return length / 2
//return folderCount!
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
i written a detailed post about how to add collection view inside custom table view cell hear hope this gives more detailed explanation than this post.