How do I make image visible when collection view cell is double tapped? - ios

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)
}

Related

swift - Correct way to pass data to UICollectionViewCell

I'm trying to create my own Book app, and using UICollectionView for listing all the books. Data for each cell is from .plist file, and I'm using custom flowLayout(to make some changes later).
So now I'm stucked with delays and lags when scrolling. I suppose I've made mistakes with passing data to cell or with cell initializing.
Cell created by .xib and custom class, just some layout and UI:
class BookCoverCell: UICollectionViewCell {
#IBOutlet weak var view1: UIView!
#IBOutlet weak var view2: UIView!
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var darkRedView: UIView!
#IBOutlet weak var lightRedView: UIView!
#IBOutlet weak var readButton: UIButton!
#IBOutlet weak var pageLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
clipsToBounds = true
self.backgroundColor = UIColor(white: 1, alpha: 0.0)
view1.layer.cornerRadius = 10
view2.layer.cornerRadius = 10
darkRedView.layer.cornerRadius = 10
lightRedView.layer.cornerRadius = 10
}
}
At ViewController's class:
class MainVC: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UIScrollViewDelegate {
#IBOutlet weak var collectionContainerView: UIView!
#IBOutlet weak var collectionView: UICollectionView!
var books: Array<Book>? {
didSet {
collectionView.reloadData()
}
}
var flowLayout = UICollectionViewFlowLayout()
override func viewDidLayoutSubviews() {
flowLayout = ZoomAndSnapFlowLayout()
collectionView.collectionViewLayout = flowLayout
}
override func viewDidLoad() {
super.viewDidLoad()
collectionContainerView.backgroundColor = UIColor(white: 1, alpha: 0.0)
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(UINib(nibName: "BookCoverCell", bundle: nil), forCellWithReuseIdentifier: "BookCoverCell");
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
books = BookStore.sharedInstance.loadBooks(plist: "Books")
}
//MARK: UICollectionViewDelegate
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if let books = books {
return books.count
}
return 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "BookCoverCell", for: indexPath) as! BookCoverCell
let book = books![indexPath.row]
let cover = book.coverImage()!
let color = book.getDominantColor()
cell.view1.backgroundColor = color
cell.imageView.image = cover
cell.pageLabel.text = "Pages: 29"
cell.readButton.setTitle("Read", for: .normal)
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let book = books?[indexPath.row]
print ("open")
}
}
And my layout now looks like:
class ZoomAndSnapFlowLayout: UICollectionViewFlowLayout {
var cellWidth = CGFloat()
var cellHeight = CGFloat()
var minLineSpacing = CGFloat()
override init() {
super.init()
self.scrollDirection = .horizontal
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func prepare() {
guard let collectionView = collectionView else { fatalError() }
cellHeight = collectionView.frame.height * 0.8
minLineSpacing = 200
cellWidth = cellHeight
itemSize = CGSize(width: cellWidth, height: cellHeight)
let verticalInsets = (collectionView.frame.height - collectionView.adjustedContentInset.top - collectionView.adjustedContentInset.bottom - itemSize.height) / 2
let horizontalInsets = (collectionView.frame.width - collectionView.adjustedContentInset.right - collectionView.adjustedContentInset.left - itemSize.width) / 2
sectionInset = UIEdgeInsets(top: verticalInsets, left: horizontalInsets, bottom: verticalInsets, right: horizontalInsets)
super.prepare()
}
}
So I'm pretty sure that have some mistakes in my code, but can't find them(( Any suggestion will be helpful for me!
UPDATE:
So first of all thanks!
I've changed my code and replace a really big image with smallest one, and function to get dominant color simply to white color for now, and things already gets better!
BUT there is small lag or delay when first scroll begins, and only with 1st and 2nd cells, while they are scrolling to the left edge of the screen. And after that all cells scrolling without lags, even first two, in both directions (left / right).
Now my code looks like:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "BookCoverCell", for: indexPath) as! BookCoverCell
let book = books![indexPath.row]
let cover = UIImage(named: "flag.png")
let color = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
cell.view1.backgroundColor = color
cell.imageView.image = cover
cell.pageLabel.text = "Pages: 29"
cell.readButton.setTitle("Read", for: .normal)
return cell
}
and UPDATE #2
removing
flowLayout = ZoomAndSnapFlowLayout()
collectionView.collectionViewLayout = flowLayout
to viewWillAppear() fix these small lags too!! Hooray!)
Read this article about Time Profiling and collection view: https://voxels.github.io/eliminating-collection-view-tearing-with-xcode-time-profiler-instrument
Since your implementation is very simple, there aren't many things that could be wrong, but you probably have the same issue that the author of the article had -- the images themselves are very large, and need to be read and resized.
They solved the issue by making appropriately sized versions of the images.
In your case getDominantColor will also be slower on large images (I am assuming that it reads the pixels to get the dominant color. You should also consider caching this color and not recalculating it every time (if you are not already doing that).

UICollectionView showing unloaded xib and not updating the content inside using swift

I have a collection view which is loaded from a .xib file. When the view opens sometimes the collection view will have loaded the content and other times it does not load any content into the cell causing just the .xib to be shown. Other times the .xib doesn't even show either. However, I don't understand why this is happening. When clicking on the cell, a new viewController opens with a detailed view which has the content loaded so the cell obviously knows what is suppose to be shown.
var currentUser: User!
var listCategories: [String] = ["Friends Lists", "Friends", "People"]
var lists = [Media]()
in viewDidLoad:
collectionView.register(UINib(nibName: "ListCell2.0", bundle: nil), forCellWithReuseIdentifier: Storyboard.listCell)
collectionView.reloadData()
observeMedia()
observeMedia():
func observeMedia() {
Media.observeNewMedia { (media) in
if !self.lists.contains(media) {
self.lists.insert(media, at: 0)
self.collectionView.reloadData()
}
}
}
viewWillAppear:
override func viewWillAppear(_ animated: Bool) {
observeMedia()
}
collectionView Methods:
extension HomeViewController
{
func numberOfSections(in collectionView: UICollectionView) -> Int {
return listCategories.count
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if section == 0 {
return lists.count
}else{
return 0
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Storyboard.listCell, for: indexPath) as! ListCell
cell.layer.applySketchShadow(color: UIColor.black, alpha: 0.08, x: 0, y: 0, blur: 10, spread: 0)
cell.layer.cornerRadius = 20
cell.layer.masksToBounds = false
cell.currentUser = self.currentUser
cell.media = self.lists[indexPath.item]
cell.mainView.setGradientBackground(colours: self.getColourFromTag(tag: self.lists[indexPath.item].tag))
return cell
}
//section header view
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView
{
let sectionHeaderView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: Storyboard.sectionHeader, for: indexPath) as! SectionHeaderView
let category = listCategories[indexPath.section]
sectionHeaderView.sectionTitle = category
return sectionHeaderView
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.performSegue(withIdentifier: Storyboard.showListDetailSegue, sender: nil)
}
the CollectionView Cell
import UIKit
import Foundation
import SAMCache
class ListCell: UICollectionViewCell {
#IBOutlet weak var nameView: UIView!
#IBOutlet weak var mainView: UIView!
#IBOutlet weak var nameButton: UIButton!
#IBOutlet weak var profileImageView: UIImageView!
//#IBOutlet weak var tagLabel: UILabel!
#IBOutlet weak var dateLabel: UILabel!
#IBOutlet weak var listTitle: UILabel!
#IBOutlet weak var boughtLabel: UILabel!
#IBOutlet weak var boughtProgress: UIProgressView!
var numOfItems = 0
var numOfBought = 0
var counter: Double = 0{
didSet{
boughtProgress.isHidden = false
let fractionalProgress = Float(counter)
boughtProgress.setProgress(fractionalProgress, animated: true)
}
}
var currentUser: User!
var media: Media! {
didSet{
if currentUser != nil{
self.updateUI()
}
}
}
var cache = SAMCache.shared()
func updateUI(){
let profileImageKey = "\(media.createdBy.uid)-profileImage"
if let image = cache?.object(forKey: profileImageKey) as? UIImage {
self.profileImageView.image = image
}else{
media.createdBy.downloadProfilePicture { [weak self] (image, error) in
if let image = image {
self?.profileImageView.image = image
self?.cache?.setObject(image, forKey: profileImageKey)
}else if error != nil {
print(error)
}
}
}
mainView.layer.cornerRadius = 20
mainView.layer.masksToBounds = true
//profile image
profileImageView.layer.cornerRadius = profileImageView.bounds.height / 2.0
profileImageView.layer.masksToBounds = true
//name
nameButton.setTitle("\(media.createdBy.firstName) \(media.createdBy.lastName)", for: [])
nameView.layer.cornerRadius = 20
nameView.layer.masksToBounds = true
//date
dateLabel.text = "\(convertDateFormatter(theDate: media.dueAt))"
dateLabel.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.3)
dateLabel.textColor = UIColor.white
dateLabel.layer.cornerRadius = dateLabel.bounds.height / 2.0
dateLabel.layer.masksToBounds = true
//title
listTitle.text = "\(media.title)"
//progress
numOfItems = media.items.count
print("num of items \(media.items.count)")
counter = Double(numOfBought)/Double(numOfItems)
boughtLabel.text = "\(numOfBought)/\(numOfItems) Bought"
boughtProgress.layer.cornerRadius = boughtProgress.bounds.height / 2.0
boughtProgress.layer.masksToBounds = true
}
#IBAction func arrowDidTap(){
print("arrow tapped")
print(media.tag)
}
func convertDateFormatter(theDate: String) -> String
{
print(theDate)
let newFormat = DateFormatter()
newFormat.dateFormat = "dd/MM/yyyy"
let dueDate = newFormat.date(from: theDate)
newFormat.dateFormat = "dd MMM yy"
print(newFormat.string(from: dueDate!))
return newFormat.string(from: dueDate!)
}
The first image shows when the view first loads. this is just what is shown in the .xib, however, the gradient has loaded, not the content
the second image shows how it should look. This is after scrolling through the view

Perform Segue from UICollectionViewCell

So I'm creating a blog app, and on the home news feed collection view (imageCollection, loaded from firebase database) I have a button. This button title depends on the Category of the image. What i'm having an issue with is performing the segue in the UICollectionViewCell class. I ran the button action with the print statement, and it worked. But when i try to add performSegue, well it doesn't let me. (Use of unresolved identifier 'performSegue')
Any tips? thank you!
P.S. i'm still fairly new to swift, so if i come off a little ignorant, i apologize
My ViewController
import UIKit
import Firebase
import FirebaseDatabase
import SDWebImage
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet weak var popImageCollection: UICollectionView!
#IBOutlet weak var imageCollection: UICollectionView!
var customImageFlowLayout = CustomImageFlowLayout()
var popImageFlowLayout = PopImagesFlowLayout()
var images = [BlogInsta]()
var popImageArray = [UIImage]()
var homePageTextArray = [NewsTextModel]()
var dbRef: DatabaseReference!
var dbPopularRef: DatabaseReference!
override func viewDidLoad() {
super.viewDidLoad()
dbRef = Database.database().reference().child("images")
dbPopularRef = Database.database().reference().child("popular")
loadDB()
loadImages()
loadText()
customImageFlowLayout = CustomImageFlowLayout()
popImageFlowLayout = PopImagesFlowLayout()
imageCollection.backgroundColor = .white
popImageCollection.backgroundColor = .white
// Do any additional setup after loading the view, typically from a nib.
}
func loadText() {
dbRef.observe(DataEventType.value, with: { (snapshot) in
if snapshot.childrenCount > 0 {
self.homePageTextArray.removeAll()
for homeText in snapshot.children.allObjects as! [DataSnapshot] {
let homeTextObject = homeText.value as? [String: AnyObject]
let titleHome = homeTextObject?["title"]
let categoryButtonText = homeTextObject?["category"]
self.imageCollection.reloadData()
let homeLabels = NewsTextModel(title: titleHome as! String?, buttonText: categoryButtonText as! String?)
self.homePageTextArray.append(homeLabels)
}
}
})
}
func loadImages() {
popImageArray.append(UIImage(named: "2")!)
popImageArray.append(UIImage(named: "3")!)
popImageArray.append(UIImage(named: "4")!)
self.popImageCollection.reloadData()
}
func loadDB() {
dbRef.observe(DataEventType.value, with: { (snapshot) in
var newImages = [BlogInsta]()
for BlogInstaSnapshot in snapshot.children {
let blogInstaObject = BlogInsta(snapshot: BlogInstaSnapshot as! DataSnapshot)
newImages.append(blogInstaObject)
}
self.images = newImages
self.imageCollection.reloadData()
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView == self.imageCollection {
return images.count
} else {
return popImageArray.count
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == self.imageCollection {
let cell = imageCollection.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! ImageCollectionViewCell
let image = images[indexPath.row]
let text: NewsTextModel
text = homePageTextArray[indexPath.row]
cell.categoryButton.setTitle(text.buttonText, for: .normal)
cell.newTitleLabel.text = text.title
cell.imageView.sd_setImage(with: URL(string: image.url), placeholderImage: UIImage(named: "1"))
return cell
} else {
let cellB = popImageCollection.dequeueReusableCell(withReuseIdentifier: "popCell", for: indexPath) as! PopularCollectionViewCell
let popPhotos = popImageArray[indexPath.row]
cellB.popularImageView.image = popPhotos
cellB.popularImageView.frame.size.width = view.frame.size.width
return cellB
}
}
}
My ImageCollectionViewCell.swift
import UIKit
import Foundation
class ImageCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var categoryButton: UIButton!
#IBOutlet weak var newTitleLabel: UILabel!
#IBOutlet weak var imageView: UIImageView!
#IBAction func categoryButtonAction(_ sender: Any) {
if categoryButton.currentTitle == "Fashion" {
print("Fashion Button Clicked")
performSegue(withIdentifier: "homeToFashion", sender: self)
}
}
override func prepareForReuse() {
super.prepareForReuse()
self.imageView.image = nil
}
}
You need a custom delegate. Do this:
protocol MyCellDelegate {
func cellWasPressed()
}
// Your cell
class ImageCollectionViewCell: UICollectionViewCell {
var delegate: MyCellDelegate?
#IBAction func categoryButtonAction(_ sender: Any) {
if categoryButton.currentTitle == "Fashion" {
print("Fashion Button Clicked")
self.delegate?.cellWasPressed()
}
}
}
// Your viewcontroller must conform to the delegate
class ViewController: MyCellDelegate {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == self.imageCollection {
let cell = imageCollection.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! ImageCollectionViewCell
// set the delegate
cell.delegate = self
// ...... rest of your cellForRowAtIndexPath
}
// Still in your VC, implement the delegate method
func cellWasPressed() {
performSegue(withIdentifier: "homeToFashion", sender: self)
}
}
You should use your own delegate. It is already described here
performSegue(withIdentifier:sender:) won't work from cell because it is UIViewController metod.
also you can make use of closure

Why I need to scroll up and down first before the collection view cell updated?

I am trying to make a category list using CollectionView, as we can see there is a brown circle that actually an UIView (Designable Background View).
I want to update that background colour from brown to random colour. but the random colour only show up after I scroll up and scroll down the CollectionView, like the .gif file in here : http://g.recordit.co/BxRf26Uw2t.gif
before scroll down the colour will be still in brown like this
after scroll up and down, the colour will be updated, but some of the item still in the brown colour like this :
here is the code of my ViewController
import UIKit
import ChameleonFramework
class FacilitiesVC: UIViewController {
#IBOutlet weak var collectionVIew: UICollectionView!
struct StoryBoard {
// Collection View
static let indoorFacilitiesCategoryCellIdentifier = "indoorFacilitiesCell"
static let numberOfColumnsPerRow : CGFloat = 3.0
static let inset: CGFloat = 10.0
static let spacing: CGFloat = 8.0
static let lineSpacing: CGFloat = 8.0
//segue Identifiers
}
var indoorFacilitiesCategoryData = [FacilitiesCategory]()
var outdoorFacilitiesCategoryData = [FacilitiesCategory]()
override func viewDidLoad() {
super.viewDidLoad()
getIndoorOutdoorFacilitiesData()
}
}
extension FacilitiesVC {
func getIndoorOutdoorFacilitiesData() {
let facilitiesData = FacilitiesCategoryLibrary.fetchFacilitiesCategory()
// distinguishing between indoor and outdoor data
for facData in facilitiesData {
if facData.type == "Indoor Facility" {
indoorFacilitiesCategoryData.append(facData)
} else {
outdoorFacilitiesCategoryData.append(facData)
}
}
}
}
extension FacilitiesVC : UICollectionViewDataSource {
// MARK: - UICollectionViewDataSource
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return indoorFacilitiesCategoryData.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: StoryBoard.indoorFacilitiesCategoryCellIdentifier, for: indexPath) as! IndoorFacilitiesCell
cell.indoorFacilitiesCategoryData = indoorFacilitiesCategoryData[indexPath.item]
cell.designableBackgroundView.backgroundColor = RandomFlatColor()
cell.layer.borderColor = UIColor.lightGray.cgColor
cell.layer.borderWidth = 1
return cell
}
}
and here is the code of CollectionViewCell
import UIKit
import ChameleonFramework
class IndoorFacilitiesCell: UICollectionViewCell {
#IBOutlet weak var designableBackgroundView: DesignableUIView!
#IBOutlet weak var iconImageView: UIImageView!
#IBOutlet weak var icontitleLabel: UILabel!
var indoorFacilitiesCategoryData : FacilitiesCategory? {
didSet {
updateUI()
}
}
}
extension IndoorFacilitiesCell {
func updateUI() {
guard let indoorData = indoorFacilitiesCategoryData else {return}
iconImageView.image = UIImage(named: indoorData.logo)
icontitleLabel.text = indoorData.categoryName
}
}
what went wrong in here? what should I do to fix that?

UICollectionView with Custom Cell Breaking UICollectionViewDataSource Protocol

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.

Resources