Data has been replaced or missing while scrolling collectionview - ios

i am implementing collection view as my ChatMessagViewController and i am populating message in collectionview all things works perfect for me but issue is that when i scrolled collection view message was . issing or replaced on scroll let me show you my code for populating collectionview
here i am adding screen shot for what output i get before scrolling and after scrolling please have a look
func loadMessageData(){
self.message.removeAll()
guard let uid = Auth.auth().currentUser?.uid else{
return
}
let userref = Database.database().reference().child("Message").child(uid)
userref.child(self.senderID!).observe(.childAdded, with: { (snapshot) in
print(snapshot)
if let dictonary = snapshot.value as? [String:AnyObject]{
let key = snapshot.key
let mainDict = NSMutableDictionary()
mainDict.setObject(key, forKey: "userid" as NSCopying)
self.namesArray.add(mainDict)
let message = Message(dictionary: dictonary)
self.message.append(message)
self.timer?.invalidate()
self.timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(self.handleReload), userInfo: nil, repeats: false)
}
}, withCancel: nil)
}
extension ChatViewController: UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return message.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellID, for: indexPath) as! ChatMessageCell
let message1 = message[indexPath.item]
cell.tetxtView.text = message1.msg
cell.bubbleWidthAnchor?.constant = estimatedFrameForText(text: message1.msg!).width + 32
let ketID = message1.key_id
if ketID == Auth.auth().currentUser?.uid{
cell.bubbleView.backgroundColor = UIColor(red: 255, green: 255, blue: 255, alpha: 1)
cell.bubbleViewRightAnchor?.isActive = false
cell.bubbleViewLeftAnchor?.isActive = true
}else{
cell.bubbleView.backgroundColor = UIColor(red: 0/255, green: 158/255, blue: 214/255, alpha: 1)
cell.tetxtView.textColor = UIColor.white
cell.bubbleViewRightAnchor?.isActive = true
cell.bubbleViewLeftAnchor?.isActive = false
}
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
var height: CGFloat = 80
if let mesg = message[indexPath.item].msg{
height = estimatedFrameForText(text: mesg).height + 20
}
return CGSize(width: view.frame.width, height: height)
}
}
and here is the collectionview methods for populating
issue is that when i scroll the message was replaced or missing
please check screen shot first i am getting messages and after scrolling i came back to top message is missing

cell.tetxtView.textColor is dequeued make sure to add it inside the if also
if ketID == Auth.auth().currentUser?.uid{
cell.bubbleView.backgroundColor = UIColor(red: 255, green: 255, blue: 255, alpha: 1)
cell.tetxtView.textColor = UIColor.black /////// here
cell.bubbleViewRightAnchor?.isActive = false
cell.bubbleViewLeftAnchor?.isActive = true
}else{
cell.bubbleView.backgroundColor = UIColor(red: 0/255, green: 158/255, blue: 214/255, alpha: 1)
cell.tetxtView.textColor = UIColor.white
cell.bubbleViewRightAnchor?.isActive = true
cell.bubbleViewLeftAnchor?.isActive = false
}
The text color is white so it same as the background of it's superview , hence doesn't appear

Related

Cardlayout swipe left programmatically not working

I am using pod 'CardsLayout' to my project.
cardlayout library
The image is
this library doesn't have functionality of swipe left and swipe right programmatically. so, i checked that, it is using UICollectionView. So, i thought that i can use selectItem by following code.
func onNextButtonClicked(collectionViewCell:QuestionrieViewCell) {
let currentIndex = collectionViewCell.getIndexPath().row
if currentIndex < getIndexPaths().count-1{
collectionView.deselectItem(at: collectionViewCell.getIndexPath(), animated: true)
collectionView.selectItem(at: getIndexPaths()[collectionViewCell.getIndexPath().row + 1], animated: true, scrollPosition: .left)
self.collectionView(collectionView, didSelectItemAt:getIndexPaths()[collectionViewCell.getIndexPath().row + 1] )
}
}
func onPrevButtonClicked(collectionViewCell:QuestionrieViewCell) {
let currentIndex = collectionViewCell.getIndexPath().row
if currentIndex > 0{
collectionView.deselectItem(at: collectionViewCell.getIndexPath(), animated: true)
collectionView.selectItem(at: getIndexPaths()[collectionViewCell.getIndexPath().row - 1], animated: true, scrollPosition: .right)
self.collectionView(collectionView, didSelectItemAt:getIndexPaths()[collectionViewCell.getIndexPath().row - 1] )
}
}
I want that, swipe left and swipe right should be happen when the user click the buttons. here,
onPreviousButtonClicked working fine. whereas, swipe right button click not responding like i expected.
onNextBUttonClick gives weird response. response as below
it's stopped going to left and if i click the same right arrow button, on that stopped card, then it still slide little bit of the screen then stopped going to left.i don't know what should i do. Anyone can help me?
Edit
Additional images below.
ViewController Class is here
class ControllerQuestionarie: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate,QuestionrieViewCellDelegate{
var currentIndexPath:IndexPath?
var indexPaths:[IndexPath] = [IndexPath]()
var swipeToLeft:UISwipeGestureRecognizer?,swipeToRight:UISwipeGestureRecognizer?
var previousPage : Int = 0
#IBOutlet weak var linearProgressBar: LinearProgressBar!
#IBOutlet weak var lblQuestionNumber: UILabel!
func setIndexPaths(indexPath:IndexPath){
self.indexPaths.append(indexPath)
}
func getIndexPaths()->[IndexPath]{
return self.indexPaths
}
func onNextButtonClicked(collectionViewCell:QuestionrieViewCell) {
let currentIndex = collectionViewCell.getIndexPath().row
if currentIndex < getIndexPaths().count-1{
self.collectionView.selectItem(at: IndexPath(item: collectionViewCell.getIndexPath().row + 1, section: 0), animated: true, scrollPosition: .left)
self.collectionView(self.collectionView, didSelectItemAt: IndexPath(item: collectionViewCell.getIndexPath().row + 1, section: 0))
self.collectionView.layoutIfNeeded()
self.currentIndexPath = collectionViewCell.getIndexPath()
if self.currentIndexPath!.row == 4{
let controllerQuestionarieCompletionViewController = ControllerQuestionarieCompletionViewController.init(nibName: "ControllerQuestionarieCompletionViewController", bundle: nil)
self.navigationController!.pushViewController(controllerQuestionarieCompletionViewController, animated: true)
}
}
}
func onPrevButtonClicked(collectionViewCell:QuestionrieViewCell) {
let currentIndex = collectionViewCell.getIndexPath().row
if currentIndex > 0{
self.collectionView.selectItem(at: IndexPath(item: collectionViewCell.getIndexPath().row - 1, section: 0), animated: true, scrollPosition: .right)
self.collectionView(self.collectionView, didSelectItemAt: IndexPath(item: collectionViewCell.getIndexPath().row - 1, section: 0))
self.collectionView.layoutIfNeeded()
self.currentIndexPath = collectionViewCell.getIndexPath()
}
}
override func viewDidLoad() {
super.viewDidLoad()
collectionView.register(UINib.init(nibName: "QuestionrieViewCell", bundle: nil), forCellWithReuseIdentifier: "QuestionrieViewCell")
collectionView.collectionViewLayout = CardsCollectionViewLayout()
collectionView.dataSource = self
collectionView.delegate = self
collectionView.isPagingEnabled = true
collectionView.showsHorizontalScrollIndicator = false
let progressValue = 100/CGFloat(colors.count)
let progress = CGFloat(progressValue) * CGFloat(previousPage + 1)
lblQuestionNumber.text = "\(previousPage + 1) / \(colors.count)"
linearProgressBar.progressValue = progress
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.currentIndexPath = indexPath
// ... Other settings
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let pageWidth = scrollView.frame.size.width
let page = Int(floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1)
print (page)
if previousPage != page{
let progressValue = 100/CGFloat(colors.count)
let progress = CGFloat(progressValue) * CGFloat(page + 1)
lblQuestionNumber.text = "\(page + 1) / \(colors.count)"
linearProgressBar.progressValue = progress
}
previousPage = page
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "QuestionrieViewCell", for: indexPath) as! QuestionrieViewCell
cell.questionrieViewCellDelegate = self
cell.layer.cornerRadius = 50.0
cell.setIndexPath(indexPath: indexPath)
setIndexPaths(indexPath: indexPath)
cell.bindData()
cell.view.backgroundColor = colors[indexPath.row]
return cell
}
#IBOutlet var collectionView: UICollectionView!
var colors: [UIColor] = [
UIColor(red: 255, green: 255, blue: 255),
UIColor(red: 249, green: 220, blue: 92),
UIColor(red: 194, green: 234, blue: 189),
UIColor(red: 1, green: 25, blue: 54),
UIColor(red: 255, green: 184, blue: 209)
]
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return colors.count
}
}
extension UIColor {
convenience init(red: Int, green: Int, blue: Int) {
self.init(red: CGFloat(red)/255 ,
green: CGFloat(green)/255,
blue: CGFloat(blue)/255,
alpha: 1.0)
}
}
Yes. I did it. Finally i have tasted the answer for this question.
public func moveToPage(position:Int){
let totalPage = collectionView.contentOffset.x/collectionView.frame.width// getting totalNumberOfPage
if position < Int(totalPage){
scrollToPage(page: position, animated: true)
}
}
public func moveToNextPage()->Int{
let pageIndex = round(collectionView.contentOffset.x/collectionView.frame.width)
let pageNo = Int(pageIndex+1)
scrollToPage(page: pageNo, animated: true)
return pageNo
}
public func moveToPreviousPage()->Int{
let pageIndex = round(collectionView.contentOffset.x/collectionView.frame.width)
let pageNo = Int(pageIndex-1)
scrollToPage(page: pageNo, animated: true)
return pageNo
}
func scrollToPage(page: Int, animated: Bool) {
var frame: CGRect = self.collectionView.frame
frame.origin.x = frame.size.width * CGFloat(page)
frame.origin.y = 0
self.collectionView.scrollRectToVisible(frame, animated: animated)
}
It works like charm. Thank you

Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) getting nil in the delegate variable

I am creating a seat layout and want to get the coordinates from the view controller class in the form of array using delegate but I am getting nil from the view controller while passing the coordinates and getting this error.
Here is my view controller
import UIKit
class BookViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UITableViewDelegate, UITableViewDataSource, SeatMapDelegate {
#IBOutlet weak var dropButton: UIButton!
#IBOutlet weak var dropDownOutlet: UITableView!
#IBOutlet weak var seatMapCollection: UICollectionView!
#IBOutlet weak var dateSelecterCollection: UICollectionView!
#IBOutlet weak var timeSelecterCollection: UICollectionView!
var selectedIndexPath: IndexPath!
var dateValue = ["1","2","3","4","10","6","7","8","9","5"]
var dayValue = ["Mon","Tue","Wed","Thu","Thu","Thu","Thu","Thu","Thu","Thu"]
var month = ["jan","feb","mar","apr","Thu","Thu","Thu","Thu","Thu","Thu"]
var venue = ["Smart Cinemaz, Rupnagar","Smart Cinemaz, Fatehgarh Sahib "]
var numberSection:Int = 10
var numberOfItems:Int = 15
var seatNumber = [Int]()
var columns = [[Int]]()
var rows = [[Int]]()
var col = [2,3]
var rowno = [8,9,16]
var col1 = [5,6,7,8,9,11,12]
var rowno1 = [9]
var sectionHeader: Array<Int> = [0,4,10]
var sectionHeading = ["Gold (₹180.00)","Silver (₹150.00)","Bronze (₹100.00)"]
var rowValue = ["A","B","C","D","E","F","G","H","I","J"]
var kCounter: Int = 0
override func viewDidLoad() {
super.viewDidLoad()
self.seatMapCollection.dataSource = self
self.seatMapCollection.delegate = self
self.seatMapCollection.reloadData()
self.seatMapCollection.maximumZoomScale = 2
self.seatMapCollection.minimumZoomScale = 0.50
self.view.sendSubview(toBack: seatMapCollection)
seatMapCollection.register(UINib(nibName: "HeaderMulticolumn", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "Header")
for seat in 0...numberOfItems-1{
seatNumber.append(seat + 1)
}
self.dateSelecterCollection.dataSource = self
self.dateSelecterCollection.delegate = self
self.timeSelecterCollection.dataSource = self
self.timeSelecterCollection.delegate = self
self.dropDownOutlet.delegate = self
self.dropDownOutlet.dataSource = self
dropButton.contentHorizontalAlignment = .left
/* let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(pinchAction(sender:)))
seatMapCollection.addGestureRecognizer(pinchGesture)*/
columns.append(col)
columns.append(col1)
rows.append(rowno)
rows.append(rowno1)
}
#IBAction func dropDown(_ sender: Any) {
self.view.bringSubview(toFront: dropDownOutlet)
if dropDownOutlet.isHidden == true{
dropDownOutlet.isHidden = false
}else {
dropDownOutlet.isHidden = true
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView.tag == 1{
return 1
}else if collectionView.tag == 2{
return 1
}else{
return 15 + 2
}
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
if collectionView.tag == 1{
return 7
}else if collectionView.tag == 2{
return 5
}
else{
return 10 + 3
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView.tag == 1 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "DateSelecterCollectionViewCell", for: indexPath) as! DateSelecterCollectionViewCell
if (self.selectedIndexPath != nil && indexPath == self.selectedIndexPath){
cell.backgroundColor = UIColor.yellow
cell.dateOutlet.textColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
cell.monthOutlet.textColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
cell.dayOutlet.textColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
}
else{
cell.backgroundColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
cell.dateOutlet.textColor = UIColor.white
cell.monthOutlet.textColor = UIColor.white
cell.dayOutlet.textColor = UIColor.white
}
return cell
}else if collectionView.tag == 2{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TimeSelecterCollectionViewCell", for: indexPath) as! TimeSelecterCollectionViewCell
if (self.selectedIndexPath != nil && indexPath == self.selectedIndexPath){
cell.backgroundColor = UIColor.yellow
cell.timeOutlet.textColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
}
else{
cell.backgroundColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
cell.timeOutlet.textColor = UIColor.white
}
return cell
}
else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SeatMapCollectionViewCell", for: indexPath) as! SeatMapCollectionViewCell
cell.seatImage.isHidden = false
cell.seatImage.image = UIImage(named: "available")
for r1 in 0...rows.count-1{
for c1 in 0...columns.count-1{
if (r1 == c1){
for colum in 0...columns[c1].count-1 {
for ro in 0...rows[r1].count-1{
if indexPath.row == rows[r1][ro] && indexPath.section == columns[c1][colum]{
cell.isHidden = true
}
}
}
}
}
}
for i in 0...collectionView.numberOfSections-1{
for j in 0...sectionHeader.count-1{
// for k in 0...rowValue.count-1{
if indexPath.section != sectionHeader[j] && indexPath.row == 1{
cell.seatImage.isHidden=true
}
if indexPath.section != sectionHeader[j] && indexPath.row == 0 {
cell.seatDetail.isHidden = false
cell.seatDetail.text = rowValue[kCounter]
cell.seatDetail.textColor = UIColor.white
cell.seatImage.isHidden = true
}
if kCounter<rowValue.count-1{
kCounter=kCounter+1
}
// }
}
}
for i in 0...sectionHeader.count-1{
if indexPath.section==sectionHeader[i] && indexPath.row==0{
cell.seatDetail.isHidden=false
cell.seatDetail.text = sectionHeading[i]
cell.seatDetail.textColor = UIColor.white
cell.seatImage.isHidden = true
}
}
return cell
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if collectionView.tag == 1{
let cell = collectionView.cellForItem(at: indexPath) as! DateSelecterCollectionViewCell
if cell.isSelected == true{
cell.backgroundColor = UIColor.yellow
cell.dateOutlet.textColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
cell.monthOutlet.textColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
cell.dayOutlet.textColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
}
self.selectedIndexPath = indexPath
}else if collectionView.tag == 2 {
let cell = collectionView.cellForItem(at: indexPath) as! TimeSelecterCollectionViewCell
self.selectedIndexPath = nil
cell.backgroundColor = UIColor.yellow
cell.timeOutlet.textColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
}
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
if collectionView.tag == 1{
let cell = collectionView.cellForItem(at: indexPath) as! DateSelecterCollectionViewCell
self.selectedIndexPath = nil
cell.backgroundColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
cell.dateOutlet.textColor = UIColor.white
cell.monthOutlet.textColor = UIColor.white
cell.dayOutlet.textColor = UIColor.white
}
else if collectionView.tag == 2{
let cell = collectionView.cellForItem(at: indexPath) as! TimeSelecterCollectionViewCell
self.selectedIndexPath = nil
cell.backgroundColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
cell.timeOutlet.textColor = UIColor.white
}
}
/* #objc func pinchAction(sender:UIPinchGestureRecognizer){
var scaleValue: CGFloat!
if sender.state == .changed || sender.state == .began {
if scaleValue == nil{
seatMapCollection.transform = CGAffineTransform.init(scaleX: sender.scale, y: sender.scale)
scaleValue = sender.scale
}else{
seatMapCollection.transform = CGAffineTransform.init(scaleX: scaleValue, y: scaleValue)
}
}
}*/
//
//
//
// Drop Down Section
//
//
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return venue.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "DropDownTableViewCell") as! DropDownTableViewCell
cell.venueDetails.text = "\(venue[indexPath.row])"
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! DropDownTableViewCell
dropButton.setTitle(cell.venueDetails.text, for: .normal)
tableView.isHidden = true
}
func getSectionCoordinates() -> Array<Int> {
return sectionHeader
}
}
And here is my custom collection view class:
import UIKit
protocol SeatMapDelegate: class {
func getSectionCoordinates() -> Array<Int>
}
class CustomCollectionViewLayout: UICollectionViewLayout {
var delegate: SeatMapDelegate?
var CELL_HEIGHT = 20.0
var CELL_WIDTH = 20.0
let STATUS_BAR = UIApplication.shared.statusBarFrame.height
var cache = [UICollectionViewLayoutAttributes]()
var contentSize = CGSize.zero
var cellAttrsDictionary = [UICollectionViewLayoutAttributes]()
var cellPadding = 2.0
var sectionHeader1: Array<Int>!
var sectionHeader = [0,4,9]
override var collectionViewContentSize: CGSize{
return self.contentSize
}
var interItemsSpacing: CGFloat = 8
// 5
var contentInsets: UIEdgeInsets {
return collectionView!.contentInset
}
override func prepare() {
var counts: Int = 0
sectionHeader1=(delegate?.getSectionCoordinates())!
// Cycle through each section of the data source.
if collectionView!.numberOfSections > 0 {
for section in 0...collectionView!.numberOfSections-1 {
// Cycle through each item in the section.
if collectionView!.numberOfItems(inSection: section) > 0 {
for item in 0...collectionView!.numberOfItems(inSection: section)-1 {
// Build the UICollectionVieLayoutAttributes for the cell.
let cellIndex = NSIndexPath(item: item, section: section)
/* let width: Double = 35.0
let height: Double = 35.0
CELL_WIDTH = (delegate?.collectionView(Width: width))!
CELL_HEIGHT = (delegate?.collectionView(Height: height))!*/
if counts<sectionHeader1.count {
if item == 0 && section == sectionHeader1[counts]{
let xPos = 0.0
let yPos = Double(section) * CELL_HEIGHT
let frame = CGRect(x: xPos, y: yPos, width: 15 * CELL_WIDTH, height: CELL_HEIGHT)
let cellFinalAttribute = frame.insetBy(dx:CGFloat(cellPadding) ,dy:CGFloat(cellPadding))
let cellAttributes = UICollectionViewLayoutAttributes(forCellWith: cellIndex as IndexPath)
cellAttributes.frame = cellFinalAttribute
//cellAttributes.frame = CGRect(x: xPos, y: yPos, width: CELL_WIDTH, height: CELL_HEIGHT)
cellAttrsDictionary.append(cellAttributes)
counts=counts+1
break
}
}
let xPos = Double(item) * CELL_WIDTH
let yPos = Double(section) * CELL_HEIGHT
let frame = CGRect(x: xPos, y: yPos, width: CELL_WIDTH, height: CELL_HEIGHT)
let cellFinalAttribute = frame.insetBy(dx:CGFloat(cellPadding) ,dy:CGFloat(cellPadding))
let cellAttributes = UICollectionViewLayoutAttributes(forCellWith: cellIndex as IndexPath)
cellAttributes.frame = cellFinalAttribute
//cellAttributes.frame = CGRect(x: xPos, y: yPos, width: CELL_WIDTH, height: CELL_HEIGHT)
cellAttrsDictionary.append(cellAttributes)
}
}
}
}
// Update content size.
let contentWidth = Double(collectionView!.numberOfItems(inSection: 0)) * CELL_WIDTH
let contentHeight = Double(collectionView!.numberOfSections) * CELL_HEIGHT
self.contentSize = CGSize(width: contentWidth, height: contentHeight)
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
// Create an array to hold all elements found in our current view.
var attributesInRect = [UICollectionViewLayoutAttributes]()
// Check each element to see if it should be returned.
for cellAttributes in cellAttrsDictionary {
if rect.intersects(cellAttributes.frame) {
attributesInRect.append(cellAttributes)
}
}
// Return list of elements.
return attributesInRect
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return cellAttrsDictionary[indexPath.row]
}
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return false
}
}
I am not sure what are you trying to do with that sectionHeader1=(delegate?.getSectionCoordinates())!, but you can't use the delegate like that. In your function onPrepare there is no guarantee that your delegate was already instanced and you are unwrapping it with !, that is when you are getting the exception.

UICollectionView show strange behaviour while scrolling

I am trying to create seatMap and I want to hide the image for certain cell, but when i am doing so the image is hiding for other cells randomly not getting the issue. Suppose i hide the image for the 2nd cell the image for 4th cell is also hiding while i scroll horizontally or vertically.
Here is my ViewController Code
import UIKit
class BookViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var dropButton: UIButton!
#IBOutlet weak var dropDownOutlet: UITableView!
#IBOutlet weak var seatMapCollection: UICollectionView!
#IBOutlet weak var dateSelecterCollection: UICollectionView!
#IBOutlet weak var timeSelecterCollection: UICollectionView!
var selectedIndexPath: IndexPath!
var dateValue = ["1","2","3","4","10","6","7","8","9","5"]
var dayValue = ["Mon","Tue","Wed","Thu","Thu","Thu","Thu","Thu","Thu","Thu"]
var month = ["jan","feb","mar","apr","Thu","Thu","Thu","Thu","Thu","Thu"]
var venue = ["Smart Cinemaz, Rupnagar","Smart Cinemaz, Fatehgarh Sahib "]
var numberSection:Int = 10
var numberOfItems:Int = 15
var seatNumber = [Int]()
var columns = [[Int]]()
var rows = [[Int]]()
var col = [2,3]
var rowno = [6,7,14]
var col1 = [5,6,7,8,9,11,12]
var rowno1 = [7]
var sectionHeader = [0,4,10]
override func viewDidLoad() {
super.viewDidLoad()
self.seatMapCollection.dataSource = self
self.seatMapCollection.delegate = self
self.seatMapCollection.reloadData()
self.seatMapCollection.maximumZoomScale = 2
self.seatMapCollection.minimumZoomScale = 0.50
self.view.sendSubview(toBack: seatMapCollection)
seatMapCollection.register(UINib(nibName: "HeaderMulticolumn", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "Header")
for seat in 0...numberOfItems-1{
seatNumber.append(seat + 1)
}
self.dateSelecterCollection.dataSource = self
self.dateSelecterCollection.delegate = self
self.timeSelecterCollection.dataSource = self
self.timeSelecterCollection.delegate = self
self.dropDownOutlet.delegate = self
self.dropDownOutlet.dataSource = self
dropButton.contentHorizontalAlignment = .left
/* let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(pinchAction(sender:)))
seatMapCollection.addGestureRecognizer(pinchGesture)*/
columns.append(col)
columns.append(col1)
rows.append(rowno)
rows.append(rowno1)
}
#IBAction func dropDown(_ sender: Any) {
self.view.bringSubview(toFront: dropDownOutlet)
if dropDownOutlet.isHidden == true{
dropDownOutlet.isHidden = false
}else {
dropDownOutlet.isHidden = true
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView.tag == 1{
return 1
}else if collectionView.tag == 2{
return 1
}else{
return 15
}
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
if collectionView.tag == 1{
return 7
}else if collectionView.tag == 2{
return 5
}
else{
return 10 + 3
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView.tag == 1 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "DateSelecterCollectionViewCell", for: indexPath) as! DateSelecterCollectionViewCell
if (self.selectedIndexPath != nil && indexPath == self.selectedIndexPath){
cell.backgroundColor = UIColor.yellow
cell.dateOutlet.textColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
cell.monthOutlet.textColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
cell.dayOutlet.textColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
}
else{
cell.backgroundColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
cell.dateOutlet.textColor = UIColor.white
cell.monthOutlet.textColor = UIColor.white
cell.dayOutlet.textColor = UIColor.white
}
return cell
}else if collectionView.tag == 2{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TimeSelecterCollectionViewCell", for: indexPath) as! TimeSelecterCollectionViewCell
if (self.selectedIndexPath != nil && indexPath == self.selectedIndexPath){
cell.backgroundColor = UIColor.yellow
cell.timeOutlet.textColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
}
else{
cell.backgroundColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
cell.timeOutlet.textColor = UIColor.white
}
return cell
}
else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SeatMapCollectionViewCell", for: indexPath) as! SeatMapCollectionViewCell
for r1 in 0...rows.count-1{
for c1 in 0...columns.count-1{
if (r1 == c1){
for colum in 0...columns[c1].count-1 {
for ro in 0...rows[r1].count-1{
if indexPath.row == rows[r1][ro] && indexPath.section == columns[c1][colum]{
cell.alpha = 0
}
}
}
}
}
}
for i in 0...sectionHeader.count-1{
if indexPath.section==sectionHeader[i] && indexPath.row==0{
cell.seatDetail.alpha=1
cell.seatDetail.text = "Gold - 180"
cell.seatImage.isHidden = true
}
}
//cell.seatDetail.alpha=0
return cell
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if collectionView.tag == 1{
let cell = collectionView.cellForItem(at: indexPath) as! DateSelecterCollectionViewCell
if cell.isSelected == true{
cell.backgroundColor = UIColor.yellow
cell.dateOutlet.textColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
cell.monthOutlet.textColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
cell.dayOutlet.textColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
}
self.selectedIndexPath = indexPath
}else if collectionView.tag == 2 {
let cell = collectionView.cellForItem(at: indexPath) as! TimeSelecterCollectionViewCell
self.selectedIndexPath = nil
cell.backgroundColor = UIColor.yellow
cell.timeOutlet.textColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
}
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
if collectionView.tag == 1{
let cell = collectionView.cellForItem(at: indexPath) as! DateSelecterCollectionViewCell
self.selectedIndexPath = nil
cell.backgroundColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
cell.dateOutlet.textColor = UIColor.white
cell.monthOutlet.textColor = UIColor.white
cell.dayOutlet.textColor = UIColor.white
}
else if collectionView.tag == 2{
let cell = collectionView.cellForItem(at: indexPath) as! TimeSelecterCollectionViewCell
self.selectedIndexPath = nil
cell.backgroundColor = UIColor(red: 44/255, green: 150/255, blue: 208/255, alpha: 1)
cell.timeOutlet.textColor = UIColor.white
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return venue.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "DropDownTableViewCell") as! DropDownTableViewCell
cell.venueDetails.text = "\(venue[indexPath.row])"
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! DropDownTableViewCell
dropButton.setTitle(cell.venueDetails.text, for: .normal)
tableView.isHidden = true
}
}
Here is my Custom CollectionViewlayout
import UIKit
protocol SeatMapDelegate:class {
func collectionView(Width: Double)-> Double
func collectionView(Height: Double)-> Double }
class CustomCollectionViewLayout: UICollectionViewLayout {
var delegate: SeatMapDelegate?
var CELL_HEIGHT = 35.0
var CELL_WIDTH = 35.0
let STATUS_BAR = UIApplication.shared.statusBarFrame.height
var cache = [UICollectionViewLayoutAttributes]()
var contentSize = CGSize.zero
var cellAttrsDictionary = [UICollectionViewLayoutAttributes]()
var cellPadding = 5.0
var sectionHeader = [0,4,10]
override var collectionViewContentSize: CGSize{
return self.contentSize
}
var interItemsSpacing: CGFloat = 8
// 5
var contentInsets: UIEdgeInsets {
return collectionView!.contentInset
}
override func prepare() {
var counts: Int = 0
// Cycle through each section of the data source.
if collectionView!.numberOfSections > 0 {
for section in 0...collectionView!.numberOfSections-1 {
// Cycle through each item in the section.
if collectionView!.numberOfItems(inSection: section) > 0 {
for item in 0...collectionView!.numberOfItems(inSection: section)-1 {
// Build the UICollectionVieLayoutAttributes for the cell.
let cellIndex = NSIndexPath(item: item, section: section)
/* let width: Double = 35.0
let height: Double = 35.0
CELL_WIDTH = (delegate?.collectionView(Width: width))!
CELL_HEIGHT = (delegate?.collectionView(Height: height))!*/
if counts<sectionHeader.count {
if item == 0 && section == sectionHeader[counts]{
let xPos = 0.0
let yPos = Double(section) * CELL_HEIGHT
let frame = CGRect(x: xPos, y: yPos, width: 15 * CELL_WIDTH, height: CELL_HEIGHT)
let cellFinalAttribute = frame.insetBy(dx:CGFloat(cellPadding) ,dy:CGFloat(cellPadding))
let cellAttributes = UICollectionViewLayoutAttributes(forCellWith: cellIndex as IndexPath)
cellAttributes.frame = cellFinalAttribute
//cellAttributes.frame = CGRect(x: xPos, y: yPos, width: CELL_WIDTH, height: CELL_HEIGHT)
cellAttrsDictionary.append(cellAttributes)
counts=counts+1
break
}
}
let xPos = Double(item) * CELL_WIDTH
let yPos = Double(section) * CELL_HEIGHT
let frame = CGRect(x: xPos, y: yPos, width: CELL_WIDTH, height: CELL_HEIGHT)
let cellFinalAttribute = frame.insetBy(dx:CGFloat(cellPadding) ,dy:CGFloat(cellPadding))
let cellAttributes = UICollectionViewLayoutAttributes(forCellWith: cellIndex as IndexPath)
cellAttributes.frame = cellFinalAttribute
//cellAttributes.frame = CGRect(x: xPos, y: yPos, width: CELL_WIDTH, height: CELL_HEIGHT)
cellAttrsDictionary.append(cellAttributes)
}
}
}
}
// Update content size.
let contentWidth = Double(collectionView!.numberOfItems(inSection: 0)) * CELL_WIDTH
let contentHeight = Double(collectionView!.numberOfSections) * CELL_HEIGHT
self.contentSize = CGSize(width: contentWidth, height: contentHeight)
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
// Create an array to hold all elements found in our current view.
var attributesInRect = [UICollectionViewLayoutAttributes]()
// Check each element to see if it should be returned.
for cellAttributes in cellAttrsDictionary {
if rect.intersects(cellAttributes.frame) {
attributesInRect.append(cellAttributes)
}
}
// Return list of elements.
return attributesInRect
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return cellAttrsDictionary[indexPath.row]
}
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return false
}
}
Custom CollectionView cell class
import UIKit
class SeatMapCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var seatDetail: UILabel!
#IBOutlet weak var seatImage: UIImageView!
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
setup()
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
func setup() {
//self.layer.borderWidth = 1.0
// self.layer.borderColor = UIColor.gray.cgColor
// self.layer.cornerRadius = 5.0
}}

How to reload the collection view data in table view cell after clicking another table view cell's collection view data in swift 3?

Here I am loading collection view data dynamically in table view cell and table view cells also created on dynamic json array count and here after selecting any element in collection view which is in first table view cell then the collection view needs to be reloaded with new data which is in second table view cell can anyone help me how to reload the collection view in second table view cell swift 3 if this is not possible can anyone provide me any alternative layout to implement this ?
Here is my cell for row method
if indexPath.section == 0 {
let cell = addToCartTableView.dequeueReusableCell(withIdentifier: "addToCartCollectionCell") as! AddToCartCollectionTableViewCell
cell.configurableProduct = self.detailModel
print(self.detailModel)
cell.collectionView.tag = indexPath.row
self.addToCartTableView.setNeedsLayout()
self.addToCartTableView.layoutIfNeeded()
cell.collectionView.reloadData()
cell.cellLabel.text = detailModel?.extensionAttribute?.productOptions[indexPath.row].label
if detailModel?.extensionAttribute?.productOptions[indexPath.row].label == "Size"{
cell.sizeGuideBtn.isHidden = false
}else{
cell.sizeGuideBtn.isHidden = true
}
cell.getCurrentRow = indexPath.row
return cell
}else {
let cell = addToCartTableView.dequeueReusableCell(withIdentifier: "addToCartQtyCell") as! AddToCartQuantityTableViewCell
self.addToCartTableView.setNeedsLayout()
self.addToCartTableView.layoutIfNeeded()
cell.QtyLabel.text = "Qty"
return cell
}
Here is my table view cell code
override func awakeFromNib() {
super.awakeFromNib()
collectionView.delegate = self
collectionView.dataSource = self
print(getCurrentRow)
// Initialization code
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 50, height: 30)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
print(configurableProduct?.extensionAttribute?.productOptions[getCurrentRow].values.count)
return (configurableProduct?.extensionAttribute?.productOptions[getCurrentRow].values.count)!
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! AddToCartCollectionViewCell
if indexPath.item == 0 {
let items = configurableProduct?.extensionAttribute?.productOptions[getCurrentRow].values[indexPath.row]
cell.collectionLabel.text = "\(items?.valueIndex as! Int)"
if indexPath.item == self.selectedIndex{
cell.backgroundColor = #colorLiteral(red: 0.007509540026, green: 0.6581087804, blue: 0.01165772038, alpha: 1)
}else if self.selectedIndex == nil {
cell.backgroundColor = UIColor.white
}else{
cell.backgroundColor = UIColor.white
}
}
else {
if selectedValue != nil {
for item in (self.configurableProduct?.extensionAttribute?.productStock)! {
// let jsonStr = "{\"label\":\"57-175\",\"stock\":0}"
let dict = try! JSONSerialization.jsonObject(with: item.data(using: .utf8)!, options: []) as! [String:Any]
let labelValue = dict["label"] as! String
print(labelValue)
let values:[String] = labelValue.components(separatedBy: "-")
print(values)
self.colorNumber = Int(values[0])
self.sizeNumber = Int(values[1])
let stock = dict["stock"] as! Int
let value = selectedValue
if value == self.colorNumber {
if stock != 0 {
self.sizeArray.append(self.sizeNumber!)
print(self.sizeArray)
cell.collectionLabel.text = "\(self.sizeNumber)"
}
}
}
if indexPath.item == self.selectedIndex{
cell.backgroundColor = #colorLiteral(red: 0.007509540026, green: 0.6581087804, blue: 0.01165772038, alpha: 1)
}else if self.selectedIndex == nil {
cell.backgroundColor = UIColor.white
}else{
cell.backgroundColor = UIColor.white
}
}
else {
let items = configurableProduct?.extensionAttribute?.productOptions[getCurrentRow].values[indexPath.item]
print(items?.valueIndex)
for item in (self.configurableProduct?.extensionAttribute?.productStock)! {
// let jsonStr = "{\"label\":\"57-175\",\"stock\":0}"
let dict = try! JSONSerialization.jsonObject(with: item.data(using: .utf8)!, options: []) as! [String:Any]
let labelValue = dict["label"] as! String
print(labelValue)
let values:[String] = labelValue.components(separatedBy: "-")
print(values)
self.colorNumber = Int(values[0])
self.sizeNumber = Int(values[1])
let stock = dict["stock"] as! Int
let value = self.selectedIndex
if value == self.colorNumber {
if stock != 0 {
self.sizeArray.append(self.sizeNumber!)
print(self.sizeArray)
cell.collectionLabel.text = "\(items?.valueIndex as! Int)"
}
}else {
cell.collectionLabel.text = "\(items?.valueIndex as! Int)"
}
}
if indexPath.item == self.selectedIndex{
cell.backgroundColor = #colorLiteral(red: 0.007509540026, green: 0.6581087804, blue: 0.01165772038, alpha: 1)
}else if self.selectedIndex == nil {
cell.backgroundColor = UIColor.white
}else{
cell.backgroundColor = UIColor.white
}
}
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if collectionView.tag == 0 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! AddToCartCollectionViewCell
cell.backgroundColor = #colorLiteral(red: 0.007509540026, green: 0.6581087804, blue: 0.01165772038, alpha: 1)
cell.collectionLabel.layer.cornerRadius = 15
cell.collectionLabel.layer.borderColor = #colorLiteral(red: 0.007509540026, green: 0.6581087804, blue: 0.01165772038, alpha: 1)
self.dataSelected = true
self.selectedIndex = indexPath.item
print(self.selectedIndex)
self.collectionView.reloadData()
self.sizeArray.removeAll()
self.selectedValue = configurableProduct?.extensionAttribute?.productOptions[1].values[indexPath.item].valueIndex
self.getCurrentRow = 1
self.collectionView.reloadData()
print(self.selectedValue)
}
else {
print(collectionView.tag)
}
}
here is my layout image
in didSelectItemAt of collection view, reload the table cell which contains size by doing
let indexpath = IndexPath(item: value, section: 0)
tableview.reloadRows(at: [indexpath], with: .none)
here value is position of row which you want to upate
Create a new variable "cellObj" which data type is same as you custom cell where you added collection view.
var cellObj:AddToCartCollectionTableViewCell!
After add assign cellObj value after this line.
let cell = addToCartTableView.dequeueReusableCell(withIdentifier: "addToCartCollectionCell") as! AddToCartCollectionTableViewCell
cellObj = cell
*** After doing you are able to reload collection view any where.
cellObj.collectionView.reloadData()
DispatchQueue.main.async {
// cell!.tableView.reloadData()
collectionView.reloadItems(at: [indexPath])
cell!.tableView.reloadData()
}
})

How to tag a dequeueReusableCell without mess the content?

I have used a dequeueReusableCell in a list, and there are 4 UILabel in the cell. There are screenshots below.
Whichever the label has a prefix of "-", it will be Red, but after scroll it a few pages, the number has become a mess. Wonder if there a way to avoid this?
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "RecipeTableCell", for: indexPath)
let currentRecipe = recipes?[indexPath.row]
let colorRed = UIColor(red: 0xFE/255, green: 0x38/255, blue: 0x24/255, alpha: 1) //FE3824
(cell.viewWithTag(100) as! UIImageView).image = UIImage(named: currentRecipe?.pic ?? "")
(cell.viewWithTag(200) as! UILabel).text = currentRecipe?.name
let hungryLabel = cell.viewWithTag(301) as! UILabel
hungryLabel.text = currentRecipe?.hungry_value
if (currentRecipe?.hungry_value!.hasPrefix("-"))! {
hungryLabel.textColor = colorRed
}
let healthLabel = (cell.viewWithTag(302) as! UILabel)
healthLabel.text = currentRecipe?.health_value
if (currentRecipe?.health_value!.hasPrefix("-"))! {
healthLabel.textColor = colorRed
}
let sanityLabel = (cell.viewWithTag(303) as! UILabel)
sanityLabel.text = currentRecipe?.sanity_value
if (currentRecipe?.sanity_value!.hasPrefix("-"))! {
sanityLabel.textColor = colorRed
}
(cell.viewWithTag(304) as! UILabel).text = currentRecipe?.duration
return cell
}
Thanks you guys.
I add a Black Color to 'else', it works, thank you
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "RecipeTableCell", for: indexPath)
let currentRecipe = recipes?[indexPath.row]
let colorRed = UIColor(red: 0xFE/255, green: 0x38/255, blue: 0x24/255, alpha: 1) //FE3824
let colorBlack = UIColor(red: 74/255, green: 74/255, blue: 74/255, alpha: 1) //747474
(cell.viewWithTag(100) as! UIImageView).image = UIImage(named: currentRecipe?.pic ?? "")
(cell.viewWithTag(200) as! UILabel).text = currentRecipe?.name
let hungryLabel = cell.viewWithTag(301) as! UILabel
hungryLabel.text = currentRecipe?.hungry_value
if (currentRecipe?.hungry_value!.hasPrefix("-"))! {
hungryLabel.textColor = colorRed
} else {
hungryLabel.textColor = colorBlack
}
let healthLabel = (cell.viewWithTag(302) as! UILabel)
healthLabel.text = currentRecipe?.health_value
if (currentRecipe?.health_value!.hasPrefix("-"))! {
healthLabel.textColor = colorRed
} else {
healthLabel.textColor = colorBlack
}
let sanityLabel = (cell.viewWithTag(303) as! UILabel)
sanityLabel.text = currentRecipe?.sanity_value
if (currentRecipe?.sanity_value!.hasPrefix("-"))! {
sanityLabel.textColor = colorRed
} else {
sanityLabel.textColor = colorBlack
}
(cell.viewWithTag(304) as! UILabel).text = currentRecipe?.duration
return cell
}
in your cellForRowAt method you need to check if value is positive the color is black and if negative the it is red. For example
label.color = black
if negativeValue {
lagel.color = red
}

Resources