Swift FSCalendar add event based on array of date - ios

In my case, I am trying to customise FSCalendar. Here, add multiple event in calendar options available but it is showing three dots. I need to do If two same date in the array need to show two dot also if three need to show three dot but above three also need to show only three dot. How to achieve this?
https://iosexample.com/a-fully-customizable-ios-calendar-library-compatible-with-objective-c-and-swift/
My Code
var datesWithEvent = ["02-09-2019", "03-09-2019", "07-09-2019", "09-09-2019"]
var datesWithMultipleEvents = ["03-09-2019", "03-09-2019", "02-09-2019", "09-09-2019"]
func calendar(_ calendar: FSCalendar, numberOfEventsFor date: Date) -> Int {
let dateString = self.dateFormatter.string(from: date)
if self.datesWithEvent.contains(dateString) {
return 1
}
if self.datesWithMultipleEvents.contains(dateString) {
return 3
}
return 0
}
func calendar(_ calendar: FSCalendar, appearance: FSCalendarAppearance, eventDefaultColorsFor date: Date) -> [UIColor]? {
let key = self.dateFormatter.string(from: date)
if self.datesWithMultipleEvents.contains(key) {
return [UIColor.magenta, appearance.eventDefaultColor, UIColor.black]
}
return nil
}

Here,Below answer for adjusting the FSCalendar dot UI count based on JSON array Data.
func calendar(_ calendar: FSCalendar, numberOfEventsFor date: Date) -> Int {
let dateString = self.dateFormatter.string(from: date)
if self.datesWithEvent.contains(dateString) {
return 1 // Here, We have to assign JSON count key value based on duplication it will increase dot count UI.
}
return 0
}

Related

FSCalendar event dot disappears after selecting the day

I am using this code to add dots for events and the dots appear perfectly fine but when I select the day with the event, the dot permanently disappears and even when selecting another day, the dot still doesnt reappear.
here is my code to make the dots appear at the start
func calendar(_ calendar: FSCalendar, willDisplay cell: FSCalendarCell, for date: Date, at monthPosition: FSCalendarMonthPosition) {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let dateString = dateFormatter.string(from: date)
cell.eventIndicator.isHidden = false
for wp in worriesPanic{
let wPDateStr = dateFormatter.string(from: wp.date!)
if wPDateStr == dateString {
cell.eventIndicator.numberOfEvents = 1
break
}
}
}
You can use image method for show event.
func calendar(_ calendar: FSCalendar, imageFor date: Date) -> UIImage? {
let dateString = self.dateFormatter1.string(from: date)
if self.yourDate.contains(dateString) {
return UIImage(named:"img")
}
return nil
}

How to remove all weekends in FSCalendar

I would like to remove all weekends from my FSCalendar to show only weekdays. Thank you in advance. So far I manage that I can't pick weekend days from calendar. I would like to that weekends do not show at all
func calendar(_ calendar: FSCalendar, shouldSelect date: Date, at monthPosition: FSCalendarMonthPosition) -> Bool {
return CheckSatSunday(today: date)
}
Disable picking weekedn on calendar
func CheckSatSunday(today:Date) ->Bool{
var DayExist:Bool
// let today = NSDate()
let calendar =
NSCalendar(calendarIdentifier:NSCalendar.Identifier.gregorian)
let components = calendar!.components([.weekday], from: today)
if components.weekday == 1 {
print("Sunday")
DayExist = false
} else if components.weekday == 7{
print("Saturday")
DayExist = false
} else{
print("It's not Saturday and Sunday ")
DayExist = true
}
print("weekday :\(String(describing: components.weekday)) ")
return DayExist
}
Found this other question about it, but here they refer to weekdays
How to remove days in FSCalendar Swift library
I haven't use the library personally, but I assume that if there is a public weekdays property it should be weekends as well, or at least with this you can figure out a logic to remove days selectively

iOS swift: selecting a cell I want to select the entire row

I have a calendar, and I want to select an entire row (week) when I select a day.. this is my code so far:
//When a date is selected
func calendar(_ calendar: JTAppleCalendarView, didSelectDate date: Date, cell: JTAppleCell?, cellState: CellState) {
selectTheWeek(of: date)
setupLayoutCell(cell: cell, cellState: cellState)
}
func selectTheWeek(of date: Date) {
let starOfTheWeek = date.startOfWeek()
let endOfTheWeeK = date.endOfWeek()
calendarCollectionView.selectDates(from: starOfTheWeek, to: endOfTheWeeK)
}
extension Date {
func startOfWeek() -> Date {
let calendar = Calendar.autoupdatingCurrent
let currentDateComponents = calendar.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self)
return calendar.date(from: currentDateComponents)!
}
func endOfWeek() -> Date {
let cal = Calendar.autoupdatingCurrent
var component = DateComponents()
component.weekOfYear = 1
component.day = -1
return cal.date(byAdding: component, to: startOfWeek())!
}
}
the problem is that I'm having an infinite loop, and it's clear the reason.
But I don't know how to prevent it. Any help?
JTAppleCalender is an external library. It's an extension of a collectionView.
You can use 2 techniques to break the loop.
First:
calendarViewselectDates(from: starOfTheWeek, to: endOfTheWeeK, triggerSelectionDelegate: false)
By setting triggerSelectionDelegate to false, your delegate function didSelect will not be called.
Second:
If you are using MasterBranch code (which i'll be releasing in a week or so), you can know whether or not your selection is programmer initiated vs user initiated. You know this by --> cellState.
if cellState.selectionType == .programatic {
// ignore stuff
} else {
// Do stuff
}
You can put this if statement in your shouldSelect function.
I know this is a not the best possible solution but it could work to avoid your issue
//When a date is selected
var shouldSelectWeek = true
func calendar(_ calendar: JTAppleCalendarView, didSelectDate date: Date, cell: JTAppleCell?, cellState: CellState) {
if shouldSelectWeek{
selectTheWeek(of: date)
shouldSelectWeek = false
}
setupLayoutCell(cell: cell, cellState: cellState)
}
func selectTheWeek(of date: Date) {
let starOfTheWeek = date.startOfWeek()
let endOfTheWeeK = date.endOfWeek()
calendarCollectionView.selectDates(from: starOfTheWeek, to: endOfTheWeeK)
}
extension Date {
func startOfWeek() -> Date {
let calendar = Calendar.autoupdatingCurrent
let currentDateComponents = calendar.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self)
return calendar.date(from: currentDateComponents)!
}
func endOfWeek() -> Date {
let cal = Calendar.autoupdatingCurrent
var component = DateComponents()
component.weekOfYear = 1
component.day = -1
return cal.date(byAdding: component, to: startOfWeek())!
}
Just add a new boolean variable like var shouldIgnoreDateSelection = false and then you just do
func calendar(_ calendar: JTAppleCalendarView, didSelectDate date: Date, cell: JTAppleCell?, cellState: CellState) {
if shouldIgnoreDateSelection == false {
selectTheWeek(of: date)
}
setupLayoutCell(cell: cell, cellState: cellState)
}
func selectTheWeek(of date: Date) {
let starOfTheWeek = date.startOfWeek()
let endOfTheWeeK = date.endOfWeek()
shouldIgnoreDateSelection = true
calendarCollectionView.selectDates(from: starOfTheWeek, to: endOfTheWeeK)
shouldIgnoreDateSelection = false
}

How to customise UIDatePicker to achieve the following output?

This is the picker that contains the day, date, and month as input, also, in one scroll, is there any way to achieve this kind of functionality from picker/datepicker in iOS?
For such a case, you should add it as a UIPickerView. Assuming that the issue would be: How to fill its values by the days of the current month? to make it more clear, I would mention it as steps:
You should get the current month start and end dates. You could find how to achieve it by checking this answer.
You will need to get all days -with the desired format- between the start and the end dates. You could find how to achieve it by checking this answer.
After getting all days in the current month, you could fill the date picker datasource method easily.
Implementation:
class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
var currentMonthDays: [String] {
var array = [String]()
var date = Date().startOfMonth() // first date
let endDate = Date().endOfMonth()
let fmt = DateFormatter()
//fmt.dateFormat = "dd/MM/yyyy"
fmt.dateFormat = "EEE dd MMM"
while date <= endDate {
date = Calendar.current.date(byAdding: .day, value: 1, to: date)!
array.append(fmt.string(from: date))
}
return array
}
override func viewDidLoad() {
super.viewDidLoad()
print(currentMonthDays)
}
// Picker View Data Soruce & delegate Methods
// REMARK: make sure to connect pickerview datasource/delegate to your view controller,
// I did it from the storyboard
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return currentMonthDays.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return currentMonthDays[row]
}
}
// Step #1:
extension Date {
func startOfMonth() -> Date {
return Calendar.current.date(from: Calendar.current.dateComponents([.year, .month], from: Calendar.current.startOfDay(for: self)))!
}
func endOfMonth() -> Date {
return Calendar.current.date(byAdding: DateComponents(month: 1, day: -1), to: self.startOfMonth())!
}
}
Do below steps :-
1. You have to change date with applying DateFormatter().
2. Save all dates (string format) in your NSArray or NSMutableArray for your UIPickerView Datasource method.
3. Then call UIPickerView Datasource and Delegate methods for fetch your result.
For date conversion you can apply below code.
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "EEE dd MMM"
let currentDate = NSDate()
let convertedDateString = dateFormatter.string(from:currentDate as Date)
print("convertedDate: ", convertedDateString)

How to Add events to FSCalendar Swift?

I am using FSCalendar to add calendar UI in my project . But I am unable to find any solution to add events to the calendar. So any ideas on how to add events to FSCalendar or any third party calendar framework?
To Set Events Base On Dates..
Instance of DateFormatter And Variables:
var datesWithEvent = ["2015-10-03", "2015-10-06", "2015-10-12", "2015-10-25"]
var datesWithMultipleEvents = ["2015-10-08", "2015-10-16", "2015-10-20", "2015-10-28"]
fileprivate lazy var dateFormatter2: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
return formatter
}()
next is... DataSource Function:
func calendar(_ calendar: FSCalendar, numberOfEventsFor date: Date) -> Int {
let dateString = self.dateFormatter2.string(from: date)
if self.datesWithEvent.contains(dateString) {
return 1
}
if self.datesWithMultipleEvents.contains(dateString) {
return 3
}
return 0
}
I Hope This Help You, This Code is Base On FsCalendar Sample Project.
I have an array that contains events's dates and the number of event on this date what I did is:
1- Comparing dates(comparing dates without time using compareDate(data.eventDate!, toDate: date, toUnitGranularity: .Day)) from my array with date(in the function)
2- If they're equal I'll add date to an array(datesWithEvent) without time so I can compare it later without problems
3- return true when it finds the right dates
var datesWithEvent:[NSDate] = []
func calendar(calendar: FSCalendar, hasEventForDate date: NSDate) -> Bool {
for data in eventsArray{
let order = NSCalendar.currentCalendar().compareDate(data.eventDate!, toDate: date, toUnitGranularity: .Day)
if order == NSComparisonResult.OrderedSame{
let unitFlags: NSCalendarUnit = [ .Day, .Month, .Year]
let calendar2: NSCalendar = NSCalendar.currentCalendar()
let components: NSDateComponents = calendar2.components(unitFlags, fromDate: data.eventDate!)
datesWithEvent.append(calendar2.dateFromComponents(components)!)
}
}
return datesWithEvent.contains(date)
}
And to precise the number of event on this date (different number of dots) I've added this code
func calendar(calendar: FSCalendar, numberOfEventsForDate date: NSDate) -> Int {
for data in eventsArray{
let order = NSCalendar.currentCalendar().compareDate(data.eventDate!, toDate: date, toUnitGranularity: .Day)
if order == NSComparisonResult.OrderedSame{
return data.numberOfEvent!
}
}
return 0
}
Try this code,in Objective-C
- (NSInteger)calendar:(FSCalendar *)calendar numberOfEventsForDate:(NSDate*)date
{
NSString *dateString = [calendar stringFromDate:date format:#"yyyy-MM-dd"];
if ([_datesWithEvent containsObject:dateString]){
return 1;
}
else{
NSLog(#"........Events List........");
}
return 0;
}
try these code it will help you
func calendar(_ calendar: FSCalendar, numberOfEventsFor date: Date) -> Int {
let dateString = self.dateFormatter.string(from: date)
print(dateString)
// datesForEvents : array of dates
if self.datesForEvents.contains(dateString) {
return 1
}
return 0

Resources