I am trying to use a UICollectionView with a custom cell. My ViewController inherits from UICollectionViewDataSource as below:
import UIKit
import Parse
class DressingRoomViewController: UIViewController,
UICollectionViewDelegateFlowLayout,
UICollectionViewDataSource {
That inheritance is causing me to break a protocol of UICollectionViewDataSource with my UICollectionView function that creates and returns the custom cell. This is the function:
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath)
-> CustomCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(
identifier,forIndexPath:indexPath) as! CustomCell
let dressingRoomIcons: [DressingRoomIcon] =
dataSource.dressingRoomIcons
let dressingRoomIcon = dressingRoomIcons[indexPath.row]
var imageView: MMImageView =
createIconImageView(dressingRoomIcon.name!)
cell.setImageV(imageView)
return cell
}
So before compilation the error is shown in the IDE. How do I get around this error? Here are the two errors I am experiencing:
Type 'DressingRoomViewController' does not conform to protocol
'UICollectionViewDataSource'
Cannot assign a value of type 'DressingRoomViewController' to a value
of type 'UICollectionViewDataSource?'
Here is the whole ViewController:
import UIKit
import Parse
class DressingRoomViewController: UIViewController,
UICollectionViewDelegateFlowLayout,
UICollectionViewDataSource {
#IBOutlet weak var MirrorImageView: UIImageView!
#IBOutlet weak var collectionView: UICollectionView!
#IBOutlet weak var heightConstraint: NSLayoutConstraint!
let identifier = "cellIdentifier"
let dataSource = DataSource()
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
let cellSpacing: CGFloat = 5
let cellsPerRow: CGFloat = 6
let numberOfItems = 12
override func viewDidLoad() {
super.viewDidLoad()
collectionView.dataSource = self
}
override func viewDidAppear(animated: Bool) {
let cellSize = (collectionView.collectionViewLayout
.collectionViewContentSize().width
/ cellsPerRow)
- (cellSpacing)
layout.itemSize = CGSize(width: cellSize, height: cellSize)
layout.minimumInteritemSpacing = cellSpacing
layout.minimumLineSpacing = cellSpacing
layout.scrollDirection = UICollectionViewScrollDirection.Horizontal
collectionView.collectionViewLayout = layout
self.heightConstraint.constant = cellSize
self.view.layoutIfNeeded()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue( segue: UIStoryboardSegue,
sender: AnyObject?) {
if (segue.identifier == "dressingRoom2MyOutfits") {
let myOutfitsViewController = segue.destinationViewController
as! MyOutfitsViewController
} else if (segue.identifier == "dressingRoom2StickerPicker") {
let myStickerPickerController = segue.destinationViewController
as! StickerPickerViewController
}
}
func imageTapped(sender: UITapGestureRecognizer) {
var imageView = sender.view as! MMImageView
println(imageView.fname)
performSegueWithIdentifier( "dressingRoom2StickerPicker",
sender: imageView)
}
}
// MARK:- UICollectionViewDataSource Delegate
extension DressingRoomViewController : UICollectionViewDataSource {
func numberOfSectionsInCollectionView(
collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return 12
}
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath)
-> CustomCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(
identifier,forIndexPath:indexPath) as! CustomCell
let dressingRoomIcons: [DressingRoomIcon] =
dataSource.dressingRoomIcons
let dressingRoomIcon = dressingRoomIcons[indexPath.row]
var imageView: MMImageView =
createIconImageView(dressingRoomIcon.name!)
cell.setImageV(imageView)
return cell
}
func createIconImageView(name: String) -> MMImageView{
var imageView :MMImageView =
MMImageView(frame:CGRectMake( 0,
0,
(collectionView.collectionViewLayout
.collectionViewContentSize().width / cellsPerRow)
- (cellSpacing),
(collectionView.collectionViewLayout
.collectionViewContentSize().width / cellsPerRow)
- (cellSpacing)))
imageView.contentMode = UIViewContentMode.ScaleAspectFit
imageView.image = UIImage(named: name)
imageView.setName(name)
imageView.backgroundColor = UIColor.clearColor()
imageView.userInteractionEnabled = true
var tapGestureRecognizer =
UITapGestureRecognizer(target: self, action: "imageTapped:")
tapGestureRecognizer.numberOfTapsRequired = 1
imageView.addGestureRecognizer(tapGestureRecognizer)
return imageView
}
}
EDIT: Here is my CustomCell:
import Foundation
import UIKit
class CustomCell: UICollectionViewCell {
var imageView = MMImageView()
func setImageV(IV: MMImageView) {
self.imageView = IV
}
}
Replace this Code
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath)
-> UICollectionViewCell {
Instead of below this :
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath)
-> CustomCell {
You can return custom cell but you can't change return type of any DataSource or Delegate method.
Related
I have a UICollectionView where the Cell's do not fill their vertical space. What adjustment should I make to ensure each cell fills up the entire cell area? Or at least all share the same height for the row they are on?
Here is the Storyboard
UICollectionViewFlowLayout
class AddServiceFlowLayout: UICollectionViewFlowLayout {
let cellsPerRow: Int
init(cellsPerRow: Int, minimumInteritemSpacing: CGFloat = 0, minimumLineSpacing: CGFloat = 0, sectionInset: UIEdgeInsets = .zero) {
self.cellsPerRow = cellsPerRow
super.init()
self.minimumInteritemSpacing = minimumInteritemSpacing
self.minimumLineSpacing = minimumLineSpacing
self.sectionInset = sectionInset
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func prepare() {
super.prepare()
guard let collectionView = collectionView else { return }
let marginsAndInsets = sectionInset.left + sectionInset.right + collectionView.safeAreaInsets.left + collectionView.safeAreaInsets.right + minimumInteritemSpacing * CGFloat(cellsPerRow - 1)
let itemWidth = ((collectionView.bounds.size.width - marginsAndInsets) / CGFloat(cellsPerRow)).rounded(.down)
itemSize = CGSize(width: itemWidth, height: itemWidth)
}
override func invalidationContext(forBoundsChange newBounds: CGRect) -> UICollectionViewLayoutInvalidationContext {
let context = super.invalidationContext(forBoundsChange: newBounds) as! UICollectionViewFlowLayoutInvalidationContext
context.invalidateFlowLayoutDelegateMetrics = newBounds.size != collectionView?.bounds.size
return context
}
}
UICollectionViewCell
class AddServiceViewCell: UICollectionViewCell {
#IBOutlet weak var labelStackView: UIStackView!
#IBOutlet weak var tvServiceName: UILabel!
#IBOutlet weak var tvQuantityNeeded: UILabel!
public var onCellTapped: (() -> ())?
override func awakeFromNib() {
super.awakeFromNib()
self.layer.cornerRadius = 10.0
}
override func prepareForReuse() {
super.prepareForReuse()
self.tvServiceName.text = nil
self.tvQuantityNeeded.show()
}
public static func nib() -> UINib {
return UINib.init(nibName: identifier, bundle: Bundle(for: ServiceLineItemCell.self))
}
public func configure(with service: TowService){
self.tvServiceName.text = service.description
if(service.calculated){
self.tvQuantityNeeded.hide()
}
}
public func eventTriggered()
{
onCellTapped?()
}
}
UIViewController
class AddServiceViewController: UIViewController {
#IBOutlet weak var collectionView: UICollectionView!
private let columnLayout = AddServiceFlowLayout(
cellsPerRow: 3,
minimumInteritemSpacing: 10,
minimumLineSpacing: 10,
sectionInset: UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
)
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Add Service"
// Register cell classes
self.collectionView!.delegate = self
self.collectionView!.dataSource = self
self.collectionView!.collectionViewLayout = columnLayout
self.collectionView!.contentInsetAdjustmentBehavior = .always
self.collectionView!.register(AddServiceViewCell.nib().self, forCellWithReuseIdentifier: AddServiceViewCell.identifier)
}
// removed for brevity ....
// MARK: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout
extension AddServiceViewController : UICollectionViewDelegateFlowLayout, UICollectionViewDelegate, UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return allServices.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: AddServiceViewCell.identifier, for: indexPath) as! AddServiceViewCell
cell.configure(with: allServices[indexPath.row])
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.onConfirmAdd(allServices[indexPath.row])
}
}
Here is a road map
1- You need to implement sizeForItemAt
2- Consider you have 3 columns per row , create a function that that accepts 3 Items ( introduced with the current indexPath.item ) from your model and manually calculate maximum height for each string in that model
3- Return the maximum height and by this you will set that height for all cells of same row
I have a collection view with a lot of images and all of these images has a heart image in the right corner. This heart image needs to be set to visible when the big image is double tapped as an indicator that it has been liked.
I have added a double tap gesture to my collection view and now I need to set the heart image to visible when this gesture happens on the selected cell.
Any suggestions to how I do it? I can't find any answers to this anywhere.
This is my collection view controller:
import UIKit
class OevelserCollectionViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
// MARK: - Properties
#IBOutlet weak var OevelserCollectionView: UICollectionView!
#IBOutlet var tap: UITapGestureRecognizer!
var oevelseCollectionViewFlowLayout: UICollectionViewFlowLayout!
let oevelseArray = OevelseArray()
// MARK: - Init
override func viewDidLoad() {
super.viewDidLoad()
setupOevelseCollectionView()
}
// MARK: - Functions
#IBAction func didDoubleTap(_ sender: UITapGestureRecognizer) {
print("tapped")
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
setupOevelseCollectionViewItemSize()
}
private func setupOevelseCollectionView() {
self.OevelserCollectionView.delegate = self
self.OevelserCollectionView.dataSource = self
let nib = UINib(nibName: "OevelseCollectionViewCell", bundle: nil)
OevelserCollectionView.register(nib, forCellWithReuseIdentifier: "OevelseCollectionViewCell")
}
private func setupOevelseCollectionViewItemSize() {
if oevelseCollectionViewFlowLayout == nil {
let numberOfItemPerRow: CGFloat = 1
let lineSpacing: CGFloat = 20
let interItemSpacing: CGFloat = 8
let width = (OevelserCollectionView.frame.width - (numberOfItemPerRow - 1) * interItemSpacing) / numberOfItemPerRow
let height = width - 50
oevelseCollectionViewFlowLayout = UICollectionViewFlowLayout()
oevelseCollectionViewFlowLayout.itemSize = CGSize(width: width, height: height)
oevelseCollectionViewFlowLayout.sectionInset = UIEdgeInsets.zero
oevelseCollectionViewFlowLayout.scrollDirection = .vertical
oevelseCollectionViewFlowLayout.minimumLineSpacing = lineSpacing
oevelseCollectionViewFlowLayout.minimumInteritemSpacing = interItemSpacing
OevelserCollectionView.setCollectionViewLayout(oevelseCollectionViewFlowLayout, animated: true)
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return oevelseArray.oevelser.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "OevelseCollectionViewCell", for: indexPath) as! OevelseCollectionViewCell
let oevelseText = oevelseArray.oevelser[indexPath.item].oevelseName
let oevelseImage = oevelseArray.oevelser[indexPath.item].oevelseImage
cell.oevelseLabel.text = oevelseText
cell.oevelseImageView.image = UIImage(named: oevelseImage)
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
}
}
And here is my collection view cell class:
import UIKit
class OevelseCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var oevelseImageView: UIImageView!
#IBOutlet weak var oevelseLabel: UILabel!
#IBOutlet weak var isLikedImageView: UIImageView!
#IBOutlet weak var heartImageWidthConstraint: NSLayoutConstraint!
override func awakeFromNib() {
super.awakeFromNib()
}
}
Inside cellForRowAt
cell.oevelseImageView.image = UIImage(named: oevelseImage)
cell.oevelseImageView.tag = indexPath.row
let tapGR = UITapGestureRecognizer(target: self, action: #selector(handleTap))
tapGR.numberOfTapsRequired = 2
cell.oevelseImageView.addGestureRecognizer(tapGR)
#objc func handleTap(_ gesture: UITapGestureRecognizer){
let index = gesture.view!.tag
guard let cell = tableView.cellForRow(at:IndexPath(row:index,section:0)) else { return }
arr[index].isLiked.toggle()
cell.isLikedImageView.image = arr[index].isLiked ? <#likeImg#> : <#defImg#>
}
OR
#objc func handleTap(_ gesture: UITapGestureRecognizer){
arr[gesture.view!.tag ].isLiked.toggle()
self.tableView.reloadRows(at:[IndexPath(row:index,section:0)],with:.none)
}
I created a UICollectionView Inside a ViewController but the UICollectionView is not loading the data I appended to the array. I tried to print from the UIcollectionView datasource and delegate but it also not printing
import UIKit
import Alamofire
import SwiftyJSON
import SDWebImage
class SelectCarViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet weak var selectedcarManufacturalLebel: UILabel!
#IBOutlet weak var selectedcarPlateNumber: UILabel!
#IBOutlet weak var selectCarCarouselCollectionView: UICollectionView!
var selecrCarsURL = "https://my.api.mockaroo.com/cars.json?key=86f86980"
var selectCarArray : [SelectCarDataModel] = [SelectCarDataModel]()
let selectCarFromJSON = SelectCarDataModel()
override func viewDidLoad() {
super.viewDidLoad()
selectCarCarouselCollectionView.delegate = self
selectCarCarouselCollectionView.dataSource = self
//register custom sell nib file
selectCarCarouselCollectionView.register(UINib.init(nibName: "SelectCarViewCell", bundle: nil), forCellWithReuseIdentifier: "selectIdentifier")
//Add flowyout function
addFlowlayOut()
getselectCarData(url: selecrCarsURL)
selectCarCarouselCollectionView.reloadData()
}
//MARK:- Add carousel flowlayout for viewcontroller collectionview
func addFlowlayOut() {
let flowlayout = UPCarouselFlowLayout()
flowlayout.itemSize = CGSize(width: UIScreen.main.bounds.size.width - 60, height: selectCarCarouselCollectionView.frame.size.height)
flowlayout.scrollDirection = .horizontal
flowlayout.sideItemScale = 0.8
flowlayout.sideItemAlpha = 1.0
flowlayout.spacingMode = .fixed(spacing: 5.0)
selectCarCarouselCollectionView.collectionViewLayout = flowlayout
}
//MARK:- Select Car Newtworking
func getselectCarData(url: String) {
Alamofire.request(url, method: .get).responseJSON {
response in
if response.result.isSuccess {
print("Sucess Got the Selected Cars Data")
let selelectCarJSON : JSON = JSON(response.result.value!)
print(selelectCarJSON)
self.updateSelectedCar(json: selelectCarJSON)
}else {
print("error)")
}
}
}
//MARK:- Select Car Update JSON Parsing
func updateSelectedCar(json : JSON) {
//for i in 0...json.count-1 {
selectCarFromJSON.image = json["car"][0]["img"].stringValue
selectCarFromJSON.carType = json["car"][0] ["manufacturer"].stringValue
selectCarFromJSON.carModel = json["car"][0]["model"].stringValue
print("this is it \(selectCarFromJSON.image)")
//}
}
//MARK: -- UICollection Delegate and Datasourse Manipulation
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return selectCarArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = selectCarCarouselCollectionView.dequeueReusableCell(withReuseIdentifier: "selectIdentifier", for: indexPath) as! SelectCarViewCell
let selectCar = SelectCarDataModel()
selectCar.image = selectCarFromJSON.image
selectCar.carType = selectCarFromJSON.carType
selectCar.carModel = selectCarFromJSON.carModel
selectCarArray.append(selectCar)
print(selectCarArray)
cell.selectCarImage.sd_setImage(with: URL(string: selectCarArray[indexPath.row].image))
selectedcarManufacturalLebel.text = selectCarArray[indexPath.row].carType
selectedcarPlateNumber.text = selectCarArray[indexPath.row].carModel
print("this is cell\(selectCarArray[indexPath.row].image)")
selectCarCarouselCollectionView.reloadData()
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print(indexPath.row)
}
}
I expected the SDWebImage to get the URL from the JSON and populate the UICollectionView
SDWebImage show URL image in imageView not a local image.
your selectCarArray store an image not url. so it's not working.
try this:-
cell.selectCarImage.sd_setImage(with: URL(string: "https://image.shutterstock.com/image-photo/beautiful-abstract-grunge-decorative-navy-260nw-539880832.jpg"))
EDIT: seems like same question as this
I made collection view with custom layout and cell but my cell's positions were a little off so I decided to number them so that I could debug it easier. I followed this guy's answer to number my cell using labels. Somehow myLabel was nil and caused my app to crash.
I believe I have connected the outlets correctly but maybe someone could provide a list for me to check if I am doing anything wrong.
ViewController
import UIKit
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet var gridView: UICollectionView!
private let reuseIdentifier = "DesignCell"
private let numberOfSections = 1
private let numberOfCircles = 48
override func viewDidLoad() {
super.viewDidLoad()
self.gridView.registerClass(MyCell.self, forCellWithReuseIdentifier: reuseIdentifier)
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return numberOfSections
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return numberOfCircles
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! MyCell
cell.myLabel.text = String(indexPath.item) // myLabel is nil and causes a crash
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
GridLayout (my custom layout)
import UIKit
import Darwin
class GridLayout: UICollectionViewLayout {
private let numberOfColumns = 12
private let numberOfRows = 4
private var cache = [UICollectionViewLayoutAttributes]()
private var contentHeight: CGFloat = 0
private var contentWidth: CGFloat {
let insets = collectionView!.contentInset
return CGRectGetWidth(collectionView!.bounds) - insets.left - insets.right
}
override func prepareLayout() {
// some calculation i did for my cells
}
override func collectionViewContentSize() -> CGSize {
return CGSize(width: contentWidth, height: contentHeight)
}
override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var layoutAttributes = [UICollectionViewLayoutAttributes]()
for attr in cache {
if CGRectIntersectsRect(attr.frame, rect) {
layoutAttributes.append(attr)
}
}
return layoutAttributes
}
}
MyCell
import UIKit
class MyCell : UICollectionViewCell {
#IBOutlet weak var myLabel: UILabel!
}
Try to remove this line within viewDidLoad() in your ViewController class:
self.gridView.registerClass(MyCell.self, forCellWithReuseIdentifier: reuseIdentifier)
It's not needed since you have created your UICollectionView in Storyboard, connected to your dataSource and delegate, and you have added all the required methods:
numberOfItemsInSection
cellForItemAtIndexPath
I have a UICollectionView that displays 12 images. The images are not fitting in the cells, they are being cropped, but I want them to fit in the cells without being cropped.
The code that should make the image scale to fit is:
cell.imageView.contentMode = UIViewContentMode.ScaleAspectFit
cell.imageView.image = UIImage(named: name)
Here is my code for the whole viewController class and screenshot:
import UIKit
class DressingRoomViewController:
UIViewController,
UICollectionViewDelegateFlowLayout,
UICollectionViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
let identifier = "cellIdentifier"
let dataSource = DataSource()
override func viewDidLoad() {
super.viewDidLoad()
collectionView.dataSource = self
}
override func viewDidAppear(animated: Bool) {
// Notes on the equation to get the cell size:
// cells per row = 6
// cell spacing = 10
// collectionView.layout.inset = 20 (10 left, 10 right)
let cellSize = (collectionView.collectionViewLayout
.collectionViewContentSize().width - 20) / 6 - 10
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets( top: 20,
left: 10,
bottom: 10,
right: 10)
layout.itemSize = CGSize(width: cellSize, height: cellSize)
collectionView.collectionViewLayout = layout
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue( segue: UIStoryboardSegue,
sender: AnyObject?) {
if (segue.identifier == "dressingRoom2MyOutfits") {
let myOutfitsViewController = segue.destinationViewController
as! MyOutfitsViewController
}
}
}
// MARK:- UICollectionViewDataSource Delegate
extension DressingRoomViewController : UICollectionViewDataSource {
func numberOfSectionsInCollectionView(
collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return 12
}
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(
identifier,forIndexPath:indexPath) as! FruitCell
let fruits: [Fruit] = dataSource.fruits
let fruit = fruits[indexPath.row]
let name = fruit.name!
cell.imageView.contentMode = UIViewContentMode.ScaleAspectFit
cell.imageView.image = UIImage(named: name)
return cell
}
}
EDIT: Here is the FruitCell class, just in case you were wondering.
class FruitCell: UICollectionViewCell {
#IBOutlet weak var imageView: UIImageView!
}
A UIImageView that has been placed in a UICollectionViewCell from the interface builder, will not have any knowledge of a UICollectionViewFlowLayout that has been initialised programmatically. So the layout.sectionInset that I had set, was making the UICollectionViewCells smaller, and even when the UIImageView created in interface builder was constrained to the margins of the UICollectionViewCell, the UIImageView was not resizing to go smaller.
The solution was to initialise the UIImageView programmatically and set the size to be the size of the cell taking into account the cell spacing.
Here is the code:
import UIKit
class DressingRoomViewController:
UIViewController,
UICollectionViewDelegateFlowLayout,
UICollectionViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
let identifier = "cellIdentifier"
let dataSource = DataSource()
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
let cellSpacing: CGFloat = 2
let cellsPerRow: CGFloat = 6
override func viewDidLoad() {
super.viewDidLoad()
collectionView.dataSource = self
}
override func viewDidAppear(animated: Bool) {
let cellSize = (collectionView.collectionViewLayout
.collectionViewContentSize().width / cellsPerRow) - (cellSpacing)
layout.itemSize = CGSize(width: cellSize, height: cellSize)
layout.minimumInteritemSpacing = cellSpacing
layout.minimumLineSpacing = cellSpacing
collectionView.collectionViewLayout = layout
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue( segue: UIStoryboardSegue,
sender: AnyObject?) {
if (segue.identifier == "dressingRoom2MyOutfits") {
let myOutfitsViewController = segue.destinationViewController
as! MyOutfitsViewController
}
}
}
// MARK:- UICollectionViewDataSource Delegate
extension DressingRoomViewController : UICollectionViewDataSource {
func numberOfSectionsInCollectionView(
collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return 12
}
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(
identifier,forIndexPath:indexPath) as! FruitCell
let fruits: [Fruit] = dataSource.fruits
let fruit = fruits[indexPath.row]
let name = fruit.name!
var imageView :UIImageView
imageView = UIImageView(frame:CGRectMake( 0,
0,
(collectionView.collectionViewLayout
.collectionViewContentSize().width / cellsPerRow)
- (cellSpacing),
(collectionView.collectionViewLayout
.collectionViewContentSize().width / cellsPerRow)
- (cellSpacing)))
imageView.contentMode = UIViewContentMode.ScaleAspectFit
imageView.image = UIImage(named: name)
imageView.backgroundColor = UIColor.redColor()
cell.addSubview(imageView)
return cell
}
}
EDIT: I was able to crop off the empty space at the bottom of the UICollectionView by creating an outlet for the height constraint ( control + drag height constraint in interface builder onto viewController swift file) calling it heightConstraint, and then at the bottom of viewDidAppear added these two lines of code:
self.heightConstraint.constant = collectionView.contentSize.height
self.view.layoutIfNeeded()
So to show you the result with a white background on the UICollectionView and a red background on the UIImageViews, here is the result (also works on all other device sizes):