I'm using FSCalendar to create a calendar for my app but I can not get the Interactive Scope Gesture
to work. I have downloaded the example project and read through the documentation but it still crashes with this error Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
on line calendarHeightConstraint.constant = 350
. All I'm trying to achieve is the exact same as the documentation shows with the Interactive Scope Gesture but programmatically.
var calendarHeightConstraint: NSLayoutConstraint!
let calendarView: FSCalendar = {
let cl = FSCalendar()
cl.allowsMultipleSelection = false
return cl
}()
let collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.backgroundColor = UIColor(named: "backgroundColor")
cv.showsVerticalScrollIndicator = false
cv.showsHorizontalScrollIndicator = false
return cv
}()
fileprivate lazy var scopeGesture: UIPanGestureRecognizer = {
[unowned self] in
let panGesture = UIPanGestureRecognizer(target: self.calendarView, action: #selector(self.calendarView.handleScopeGesture(_:)))
panGesture.delegate = self
panGesture.minimumNumberOfTouches = 1
panGesture.maximumNumberOfTouches = 2
return panGesture
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(named: "backgroundColor")
collectionView.delegate = self
collectionView.dataSource = self
calendarView.delegate = self
calendarView.dataSource = self
calendarHeightConstraint.constant = 350
self.calendarView.select(Date())
self.view.addGestureRecognizer(self.scopeGesture)
self.calendarView.addGestureRecognizer(self.scopeGesture)
self.calendarView.scope = .week
setupLayout()
setupCollectionView()
}
func setupLayout() {
view.addSubview(calendarView)
calendarView.anchor(top: topLayoutGuide.bottomAnchor, left: view.leftAnchor, bottom: nil, right: view.rightAnchor, paddingTop: 75, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: view.frame.width, height: 350)
view.addSubview(collectionView)
collectionView.anchor(top: calendarView.bottomAnchor, left: view.leftAnchor, bottom: view.bottomAnchor, right: view.rightAnchor, paddingTop: 15, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
}
func setupCollectionView() {
collectionView.register(CalendarCollectionCell.self, forCellWithReuseIdentifier: cellId)
collectionView.dataSource = self
collectionView.delegate = self
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! CalendarCollectionCell
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.frame.width, height: 70)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 15
}
func calendar(_ calendar: FSCalendar, boundingRectWillChange bounds: CGRect, animated: Bool) {
self.calendarHeightConstraint.constant = bounds.height
self.view.layoutIfNeeded()
}
You can fix this by doing two things.
Remove the line calendarHeightConstraint.constant = 350
from viewDidLoad
.
Initialize the calendarHeightConstraint
in setupLayout
.
Instead of:
calendarView.anchor(top: topLayoutGuide.bottomAnchor, left: view.leftAnchor, bottom: nil, right: view.rightAnchor, paddingTop: 75, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: view.frame.width, height: 350)
Use:
calendarView.anchor(top: topLayoutGuide.bottomAnchor, left: view.leftAnchor, bottom: nil, right: view.rightAnchor, paddingTop: 75, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: view.frame.width, height: 0)
calendarHeightConstraint = calendarView.heightAnchor.constraint(equalToConstant: 350)
calendarHeightConstraint.isActive = true