6

I added JTAppleCalendar inside my project and I want to add some tags in some of my calendar cells. I have success adding them, but when I scroll left or right on my calendar months, cells inside tags disappear, hide, or mix, and when I scroll again and again there is more and more mixing. Do I need any protocols or delegates, etc.? Or, it is just a bug?

How can I fix that bug?

My example GitHub project

My cellForItemAt code:

func calendar(_ calendar: JTAppleCalendarView, cellForItemAt date: Date, cellState: CellState, indexPath: IndexPath) -> JTAppleCell {
        let cell = calendar.dequeueReusableCell(withReuseIdentifier: "CellView", for: indexPath) as! CellView

        var currentdate = String(describing: myCalendar.date(byAdding: .day, value: 1, to: cellState.date))
        currentdate = currentdate.substring(from: 9, length: 10)


        cell.tagList.tags.removeAll()
        cell.tagList.hide()
        cell.contentView.backgroundColor = nil
        cell.tagList.alpha = 0
        cell.tagList.numberOfRows = 0
        cell.tagList.backgroundColor = UIColor.clear
        cell.tagList.isHidden = true


        var i : Int
        i = 0

        for object in datas {

        i =  i + 1

                let clean = "\(object)".components(separatedBy: "*")

                if clean[0] == currentdate {
                   let gotag : Int
                    gotag = Int(clean[1])!
                    cell.tagList.isHidden = false
                    cell.dayLabel.text = cellState.text
                    cell.contentView.backgroundColor = UIColor.gray

                    let itemName = "Item name  \(i)"


                        cell.tagList.alpha = 1

                        if clean[1] == "1" {

                                cell.tagList.addTag(itemName, target: self, tapAction: #selector(ViewController.tap(_:)), longPressAction: #selector(ViewController.tap(_:)),backgroundColor: UIColor.orange,textColor: UIColor.white,comesTag: gotag)


                        }else if clean[1] == "2" {

                                cell.tagList.addTag(itemName, target: self, tapAction: #selector(ViewController.tap(_:)), longPressAction: #selector(ViewController.tap(_:)),backgroundColor: UIColor.green,textColor: UIColor.white,comesTag: gotag)

                        }else if clean[1] == "3" {

                                 cell.tagList.addTag(itemName, target: self, tapAction: #selector(ViewController.tap(_:)), longPressAction: #selector(ViewController.tap(_:)),backgroundColor: UIColor.brown,textColor: UIColor.white,comesTag: gotag)

                        }else if clean[1] == "4" {

                              cell.tagList.addTag(itemName, target: self, tapAction: #selector(ViewController.tap(_:)), longPressAction: #selector(ViewController.tap(_:)),backgroundColor: UIColor.black,textColor: UIColor.white,comesTag: gotag)
                        }



            }else{

                cell.tagList.backgroundColor = UIColor.clear
        }





        }


        handleCellConfiguration(cell: cell, cellState: cellState)
        return cell
    }

Bug in action:

https://github.com/LetSwiftDev/CalendarBug/blob/master/calendarbug.gif

Also you can join official JTAppleCalendar chat here https://gitter.im/patchthecode/JTAppleCalendar

SwiftDeveloper
  • 7,244
  • 14
  • 56
  • 85

2 Answers2

4

Basically, to make a weird "workaround" you should implement the classic UICollectionView (JTAppleCalendar comes from it) willDisplay method, that , as you can see , in theory it should be used to detect cell additions instead of replicate it's content, so to make this re-build of content you can follow the example also explained to the JTAppleCalendar gitHub issues and reported by swift nub here in this page.

So, your code could be:

ViewController.swift:

extension ViewController: JTAppleCalendarViewDelegate, JTAppleCalendarViewDataSource {
    func calendar(_ calendar: JTAppleCalendarView, willDisplay cell: JTAppleCell, forItemAt date: Date, cellState: CellState, indexPath: IndexPath) {
        var cell = cell as! CellView
        cell = sharedFunctionToConfigureCell(cell: cell, cellState: cellState, date: date)
    }

    func calendar(_ calendar: JTAppleCalendarView, cellForItemAt date: Date, cellState: CellState, indexPath: IndexPath) -> JTAppleCell {
        var cell = calendar.dequeueReusableCell(withReuseIdentifier: "CellView", for: indexPath) as! CellView
        cell = sharedFunctionToConfigureCell(cell: cell, cellState: cellState, date: date)
        return cell
    }

    func sharedFunctionToConfigureCell(cell: CellView, cellState: CellState, date: Date)-> CellView {
        var currentdate = String(describing: myCalendar.date(byAdding: .day, value: 1, to: cellState.date))
        currentdate = currentdate.substring(from: 9, length: 10)
        cell.tagList.tags.removeAll()
        cell.tagList.hide()
        cell.contentView.backgroundColor = nil
        cell.tagList.alpha = 0
        cell.tagList.numberOfRows = 0
        cell.tagList.backgroundColor = UIColor.clear
        cell.tagList.isHidden = true
        var i : Int
        i = 0
        for object in datas {
            i =  i + 1
            let clean = "\(object)".components(separatedBy: "*")
            if clean[0] == currentdate {
                let gotag : Int
                gotag = Int(clean[1])!
                cell.tagList.isHidden = false
                cell.dayLabel.text = cellState.text
                cell.contentView.backgroundColor = UIColor.gray
                let itemName = "Item name  \(i)"
                cell.tagList.alpha = 1
                if clean[1] == "1" {
                    cell.tagList.addTag(itemName, target: self, tapAction: #selector(ViewController.tap(_:)), longPressAction: #selector(ViewController.tap(_:)),backgroundColor: UIColor.orange,textColor: UIColor.white,comesTag: gotag)
                }else if clean[1] == "2" {
                    cell.tagList.addTag(itemName, target: self, tapAction: #selector(ViewController.tap(_:)), longPressAction: #selector(ViewController.tap(_:)),backgroundColor: UIColor.green,textColor: UIColor.white,comesTag: gotag)
                }else if clean[1] == "3" {
                    cell.tagList.addTag(itemName, target: self, tapAction: #selector(ViewController.tap(_:)), longPressAction: #selector(ViewController.tap(_:)),backgroundColor: UIColor.brown,textColor: UIColor.white,comesTag: gotag)
                }else if clean[1] == "4" {
                    cell.tagList.addTag(itemName, target: self, tapAction: #selector(ViewController.tap(_:)), longPressAction: #selector(ViewController.tap(_:)),backgroundColor: UIColor.black,textColor: UIColor.white,comesTag: gotag)
                }
            }else{
                cell.tagList.backgroundColor = UIColor.clear
            }
        }
        handleCellConfiguration(cell: cell, cellState: cellState)
        return cell
    }

    // your other code..

Update (after your tests):

After your comments, I've decided to analyze in deep your code.

First of all, there is a little bug in your mainStoryBoard and you can easily correct it replacing DesignableButton (unexistent class) with UIButton as showed in this pic to avoid the error : CalendarBug[9879:1645088] Unknown class _TtC11CalendarBug16DesignableButton in Interface Builder file.

enter image description here

After, the full JTAppleCaledar library seems hasn't any problem, in fact the author have extended also the willDisplay delegate that solved many issues around rendering of cells.

I've found your problem in the TagListView.swift class, more precisely in the method reset.

TagListView.swift:

func reset() {
  for tag in tags {
      tag.removeFromSuperview()
  }
  tags = []
  currentRow = 0
  numberOfRows = 0
}

This method remove all the tags list (the array of labels) from superview but not the other tags added in past to the superview, in other words only tags contained in the array tags. So, to avoid this issue you can reinforce your reset method by adding on line (we know they are UILabel so it's not needed to know all their tag number):

func reset() {
  for tag in tags {
      tag.removeFromSuperview()
  }
  tags = []
  currentRow = 0
  numberOfRows = 0
  self.subviews.forEach({ if $0 is UILabel { $0.removeFromSuperview()} })
}

To optimize your code you simply correct this method as:

func reset(){
    tags = []
    currentRow = 0
    numberOfRows = 0
    self.subviews.forEach({ if $0 is UILabel { $0.removeFromSuperview()} })
}

Output:

enter image description here

Alessandro Ornano
  • 34,887
  • 11
  • 106
  • 133
  • Mate I will test tonight after I will turn you . thanks for answer. If ok I will approve. – SwiftDeveloper Nov 28 '17 at 13:24
  • dude, I added that codes into ViewController on example GitHub project inside and I scrolled left month after right month again again like gif , and same issue again mixing tags. doesn't work. you can download example github project after add that codes inside view controller you will see. – SwiftDeveloper Nov 28 '17 at 17:27
  • I think maybe need to delegate tag lists ? in TagListView to inside sharedFunctionToConfigureCell – SwiftDeveloper Nov 28 '17 at 17:31
  • Do you know what is exactly the JTAppleCalendar version you try to test with your github project:currently the latest sources is tagged v.7.1.4 – Alessandro Ornano Nov 28 '17 at 18:45
  • I added Carthage support in example project after I updated again latest 7.1.4 you can download it now. – SwiftDeveloper Nov 28 '17 at 19:05
  • https://gitter.im/patchthecode/JTAppleCalendar here framework owner on chat if you need any question you can ask him – SwiftDeveloper Nov 28 '17 at 19:35
  • I've update my code, take a look and let me know. I've maded some tests and now it seems ok. – Alessandro Ornano Nov 30 '17 at 15:33
  • i will check after I will turn. – SwiftDeveloper Nov 30 '17 at 16:56
  • @Alesandro Ornano can you upload working codes to GitHub I will approve and after I will update GitHub everyone can use after thats. – SwiftDeveloper Dec 03 '17 at 12:31
  • thank you worked fine, but please update with Carthage.. so using. Carthage. I approved. now you have + 300 reps. – SwiftDeveloper Dec 04 '17 at 07:23
  • Umh, are you sure is a right idea? I've removed carthage to permit all the people to download and test immediately your project without third part tools. If I re-put this tool many people could have problem with compile or run it due to carthrage versions that nothing have to do with this bug. Anyway, If you put the code here in this answer to your github version you have my same results. – Alessandro Ornano Dec 04 '17 at 07:30
  • yeah, but im using Carthage , if with Carthage or cocoa pods thats codes work success no problem. – SwiftDeveloper Dec 04 '17 at 07:32
  • Ok let me the time to add it, I'll upload a version also with carthage to another folder in my github to have both versions ;-) – Alessandro Ornano Dec 04 '17 at 07:43
  • All right , did it. It works correctly. You can download it always from : https://github.com/aornano/CalendarBug (the folder name is WithCarthage) – Alessandro Ornano Dec 04 '17 at 08:08
  • @Alessanro Ornano, Thank you man, I think will help many people, if need any swift update you can do. Follow, Thanks – SwiftDeveloper Dec 04 '17 at 11:19
1

I don't know if this is the true issue, but you missed a function. Implement the willDisplayCell function as shown here -> https://github.com/patchthecode/JTAppleCalendar/issues/553

This might resolve your problem. but it is weird that you custom frame work doesn't warn you that you forgot to implement that function.

swift nub
  • 2,747
  • 3
  • 17
  • 39
  • which code will be add ? can you fix it with my codes ? which codes will be add in my codes ? can you answer – SwiftDeveloper Nov 25 '17 at 17:09
  • The answer is found on the link i posted. The function is called `willDisplayCell` and that link i posted explains how to implement it. Basically the willDisplay cell function will have exactly the same code as your `cellForItem` function – swift nub Nov 25 '17 at 20:42
  • can you add codes into your answer i will test after if ok , i will aprove your answer and will help many people thank you – SwiftDeveloper Nov 25 '17 at 20:58
  • I responded to your question on github – Just a coder Nov 26 '17 at 05:43
  • @iOSCalendarViewOnMyProfile when I adding that codes gives me Extra argument 'date' in call – SwiftDeveloper Nov 26 '17 at 10:36
  • @SwiftDeveloper there is no code related to the calendar I can give that will fix this, because the bug is not in the library. I could help you more, but i do not understand your code. Can you make your code simpler of github so that I can help? Make your code the simplest until you see the problem happening. – Just a coder Nov 29 '17 at 16:36