FSCalendar 사용해보신분 있나요?

아래와 같이 구현하였습니다. click된 순간 동작하는 함수해서 click된 날짜를 deselect하고 DB와 이벤트 목록데이터에 추가한 뒤, reload하여 색상을 변화시켰습니다.

import UIKit
import FSCalendar

class CalendarViewController: UIViewController, FSCalendarDataSource, FSCalendarDelegate, FSCalendarDelegateAppearance {
    
    @IBOutlet weak var calendar: FSCalendar!
    
    @IBOutlet weak var SegmentedControl: UISegmentedControl!
    
    let DB = DataBaseAPI.init()
    let Quary = DataBaseQuery.init()
    
    fileprivate lazy var dateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd"
        return formatter
    }()
    
    
    var fillDefaultColorsArray : Array<Array<String>> = []
    var fillDefaultColorsDictionary = [String : Int ]()

    
    let SegmentedBarData = ["🟩휴가","🟥훈련","🟨외출","🟦파견", "⬜️삭제"]
    let SegmentedBarColor = [UIColor.green,UIColor.red,UIColor.yellow,UIColor.blue , UIColor.clear]
    
    override func viewDidLoad() {
        
        super.viewDidLoad()
        
        //네비게이션바 세팅
        self.navigationItem.hidesBackButton = true;
        self.navigationItem.leftBarButtonItem = nil;
        let navview = Variable_Functions.init()
        self.navigationItem.titleView = navview.navView
    
       
        //세그먼트바 세팅
        SegmentedControl.removeAllSegments()
        SegmentedBarData.map({ text in
           SegmentedControl.insertSegment(withTitle: text, at: SegmentedControl.numberOfSegments, animated: false)
        })
        SegmentedControl.selectedSegmentIndex = 0
        
        
        //DB에서 불러오기
        fillDefaultColorsArray = DB.query(statement: Quary.SelectStar(Tablename: "Calendar"), ColumnNumber: 2)
        fillDefaultColorsArray.map({ each in
            fillDefaultColorsDictionary.updateValue(Int(each[1])! , forKey: each[0])
        })
        print(fillDefaultColorsDictionary)
    
        //self.calendar.deselect(self.calendar.today!)
        self.calendar.dataSource = self
        self.calendar.delegate = self
        self.calendar.register(FSCalendarCell.self, forCellReuseIdentifier: "CELL")
        self.calendar.allowsMultipleSelection = true
        self.calendar.swipeToChooseGesture.isEnabled = true
        self.calendar.appearance.caseOptions = [.headerUsesUpperCase,.weekdayUsesSingleUpperCase]
        self.calendar.appearance.borderRadius = 0
        self.calendar.appearance.borderRadius = 0
    
    }
    
    
    //날짜가 선택되어있을때
    func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) {
        let date_string = self.dateFormatter.string(from: date)
        //삭제
        if self.SegmentedControl.selectedSegmentIndex == 4 && fillDefaultColorsDictionary[date_string] != nil {
            if (DB.delete(statement: Quary.Delete(Tablename: "Calendar", Condition: "marked_date = " + "'\(date_string)'"))){
                print("delete success at calander")
            }
        }else{
            //기존 존재한다면 삭제하고 삽입한다.
            if (DB.delete(statement: Quary.Delete(Tablename: "Calendar", Condition: "marked_date = " + "'\(date_string)'"))){
                print("delete success at calander before insert")
            }
            if (DB.insert(statement: Quary.insert(Tablename: "Calendar", Values: " '\(date_string)', \(SegmentedControl.selectedSegmentIndex + 1)" ))){
                print("insert success at calander")
            }
        }
        fillDefaultColorsDictionary.updateValue(SegmentedControl.selectedSegmentIndex + 1 , forKey: date_string)
        //print(fillDefaultColorsDictionary)
        calendar.deselect(date)
        calendar.reloadData()
    }
     
    //기본색상
    func calendar(_ calendar: FSCalendar, appearance: FSCalendarAppearance, fillDefaultColorFor date: Date) -> UIColor? {
        //print("언제실행되는가?")
        let key = self.dateFormatter.string(from: date)
        if let colorindex = fillDefaultColorsDictionary[key] {
            return SegmentedBarColor[colorindex-1]
        }else{
            return  UIColor.clear
        }
    }
    
    func calendar(_ calendar: FSCalendar, appearance: FSCalendarAppearance, borderDefaultColorFor date: Date) -> UIColor? {
        
        
        let key = self.dateFormatter.string(from: date)
        if let colorindex = fillDefaultColorsDictionary[key] {
           return SegmentedBarColor[colorindex-1]
       }else{
           return  UIColor.clear
       }
    }
    
    func calendar(_ calendar: FSCalendar, appearance: FSCalendarAppearance, titleDefaultColorFor date: Date) -> UIColor? {
        return UIColor.black
    }
    
    
}

그러나 현재 문제점, 개선해야 할 점이 각각 1개 씩 있는데,
문제점 1. - click을 하였을때, 클릭한 날짜가 아닌 다른 cell이 클릭되는 듯한 애니메이션이 발생합니다. 영상은 동영상을 참고하십시오. 왜 이런 문제가 발생할까요?

개선해야 할점 1. 저희는 이런 화면을 원하고 있는데, 색상이야 나중에 이쁜 색 수정하면 되겠지만, cell의 색상을 변경하여도 주변 cell과 이어지지 않습니다. 어떤 속성을 조절해야 할까요?
목표

현재

좋아요 2

git에 코드가 없어서 코드로 확인은 못했습니다.

FSCalendar 사이트에 예제가 있는데, 그거를 돌려보니 선택 이벤트가 잘 동작합니다. 예제 프로젝트의 코드를 확인해보는 것이 좋을거 같네요.

좋아요 2

해당 git에서 제공하는 example code는 전부 확인하였으나, 문제점을 찾지 못하였습니다. 개인 git이 아닌, project git에도 push를 하였으니, 괜찮으시다면 조언 부탁드립니다! 브란치는 develop branch입니다.

좋아요 1

델리게이트를 보니까 선택된 셀의 색을 출력하는 메소드가 calendar:fillSelectionColorForDate 인거 같은데 그 구현이 안보이네요.

터치 동작으로 select/deselect 여부를 설정하고, select/deselected 상태에 따른 셀의 모습은 fillSelectionColorForDate/fillDefaultColorFor 로 하면 해결되지 않을런지.

좋아요 2

혹시 주목할만한 리포지터리에 있는 FSCalendar 사용 프로젝트들 참고해 봤나요?

못 찾으면 해당 부분의 코드만 따로 별도의 프로젝트로 만들어서 올려주면 코드레벨에서 확인해 볼 수 있을 듯 합니다.

저 코드 조각을 보고 디버깅을 하는게 쉽지가 않아서요

좋아요 1

아직 참고를 많이 못했는데 찾아보도록 하겠습니다!!

좋아요 1

델리게이트 부분을 제가 많이 안봤군요… 좀 더 찾아보겠습니다!

좋아요 1

해당 FScalendar git site에 이슈를 남기고, 주목할만한 repo에서 캘린더 관련 프로젝트를 전부 확인하였습니다.

  1. 다른 셀이 깜박 거리는 현상
    calendar의 reloaddata 함수의 동작과정에서 cell들이 재사용되기 때문에, 발생한 문제였습니다. 따라서 reload data함수를 사용하지 않고, cell을 재사용할 때 색상을 초기화해주어 해당 문제를 해결하였습니다.

  2. 예쁘게 이어주기
    background color를 변경하여 예쁘게 이어주었습니다!

좋아요 2