Some dates disappear and reappear on scroll in JTCalendar Swift - swift

I am trying to setup a calendar in my app using JTCalendar library but unfortunately i have this issue when sometimes i scroll through the app, the month in view looses the dates as described in the attached picture. I have tried to find out any information or questions in regards to this kind of issue but all was in vain. Am a bit new on this library, could anyone help me to solve this. Thanks for your time.
override func viewDidLoad() {
super.viewDidLoad()
popWithSwipe()
PLmonthArr = ["Styczeń","Luty","Marzec","Kwiecień","Maj","Czerwiec","Lipiec","Sierpień","Wrzesień","Październik","Listopad","Grudzień"]
calendarManager.menuView = calendarMenuView
calendarManager.contentView = calendarContentView
calendarManager.settings.weekDayFormat = JTCalendarWeekDayFormat.single
calendarManager.delegate = self
calendarManager.setDate(Date())
}
//MARK: View Will Appear
override func viewWillAppear(_ animated: Bool) {
currentLang = UserDefaults.standard.object(forKey:"language")as?String ?? "pl-PL"
setTextOnLanguageChange(lang:UserDefaults.standard.object(forKey:"language")as?String ?? "pl-PL")
calendarManager.reload()
}
public func calendar(_ calendar: JTCalendarManager!, prepareMenuItemView menuItemView: UIView!, date: Date!)
{
if let headerLabel = menuItemView as? UILabel{
headerLabel.textAlignment = NSTextAlignment .center
headerLabel.font = UIFont(name: "Comfortaa-Light", size: 20)
headerLabel.backgroundColor = UIColor.clear
headerLabel.textColor = UIColor.gray
let formatter = DateFormatter()
formatter.dateFormat = "MMMM yyyy"
formatter.locale = Locale(identifier: "en_US_POSIX")
let monthYear = formatter.string(from:date)
print(monthYear)
let yearFormatter = DateFormatter()
yearFormatter.dateFormat = "yyyy"
let CurrentYear = yearFormatter.string(from:date)
print(currentLang)
if currentLang == "pl-PL"{
headerLabel.text = setmonthLang(monthYear: monthYear,CurrentYear:CurrentYear).uppercased()
}else //if currentLang == "en"
{
headerLabel.text = monthYear.uppercased()
}
}
}
func numberOfMondaysInMonth(month: Int, forYear year: Int) -> Int?
{
let calendar = NSCalendar(calendarIdentifier: NSCalendar.Identifier.gregorian)!
calendar.firstWeekday = 2 // 2 == Monday
// First monday in month:
let comps = NSDateComponents()
comps.month = month
comps.year = year
comps.weekday = calendar.firstWeekday
comps.weekdayOrdinal = 1
guard let first = calendar.date(from: comps as DateComponents) else {
return nil
}
// Last monday in month:
comps.weekdayOrdinal = -1
guard let last = calendar.date(from: comps as DateComponents) else {
return nil
}
// Difference in weeks:
let weeks = calendar.components(.weekOfMonth, from: first, to: last, options: [])
return (weeks.weekOfMonth ?? 0) + 1
}
func setmonthLang(monthYear:String,CurrentYear:String)->String
{
if monthYear.contains("January")
{
return "\(PLmonthArr[0]), \(CurrentYear)"
}
else if monthYear.contains("February")
{
return "\(PLmonthArr[1]), \(CurrentYear)"
}
else if monthYear.contains("March"){
return "\(PLmonthArr[2]), \(CurrentYear)"
}
else if monthYear.contains("April"){
return "\(PLmonthArr[3]), \(CurrentYear)"
}
else if monthYear.contains("May"){
return "\(PLmonthArr[4]), \(CurrentYear)"
}
else if monthYear.contains("June"){
return "\(PLmonthArr[5]), \(CurrentYear)"
}
else if monthYear.contains("July"){
return "\(PLmonthArr[6]), \(CurrentYear)"
}
else if monthYear.contains("August"){
return "\(PLmonthArr[7]), \(CurrentYear)"
}
else if monthYear.contains("September"){
return "\(PLmonthArr[8]), \(CurrentYear)"
}
else if monthYear.contains("October"){
return "\(PLmonthArr[9]), \(CurrentYear)"
}
else if monthYear.contains("November"){
return "\(PLmonthArr[10]), \(CurrentYear)"
}
else{
return "\(PLmonthArr[11]), \(CurrentYear)"
}
}
public func calendar(_ calendar: JTCalendarManager!, prepareDayView dayView: (UIView & JTCalendarDay)!)
{
if dayView.isFromAnotherMonth(){
dayView.isHidden = true
}
let mydayview=dayView as! JTCalendarDayView
mydayview.textLabel.font = UIFont(name:"Montserrat-Regular", size:13)
mydayview.circleRatio = 2
mydayview.backgroundColor = UIColor.white
mydayview.circleView.layer.cornerRadius = 1
mydayview.textLabel.textColor = UIColor.gray
mydayview.isFromAnotherMonth = false
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd"
let dateStr = dateFormatter.string(from: mydayview.date)
print(dateStr)
if(isAVailableOnSelectedDate(dateStr: dateStr)){
let now = Date()
dateFormatter.dateFormat = "yyyy-MM-dd"
print(dateFormatter.string(from: now))
if let currentDate = calendarManager.date() {
let currentDateString = String(describing: currentDate)
if dateFormatter.string(from: now) == currentDateString.prefix(10){
mydayview.circleView.isHidden = false
mydayview.circleView.backgroundColor = UIColor.lightGray.withAlphaComponent(0.5)
mydayview.textLabel.textColor = UIColor.black
}
else{
mydayview.circleView.isHidden = false
mydayview.textLabel.textColor = UIColor.black
mydayview.circleView.backgroundColor = UIColor.lightGray.withAlphaComponent(0.5)
}
}
}
else if calendarManager.dateHelper.date(calendarContentView.date, isTheSameMonthThan: mydayview.date)
{
mydayview.circleView.isHidden = true;
// mydayview.backgroundColor = UIColor.white
// mydayview.dotView.backgroundColor = UIColor.red
mydayview.textLabel.textColor = UIColor.gray
}
if calendarManager.dateHelper.date(Date(), isTheSameDayThan: mydayview.date){
mydayview.circleView.isHidden = false
mydayview.circleView.backgroundColor = UIColor.white
mydayview.layer.borderColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
mydayview.layer.borderWidth = 1
} else if mydayview.date > Date() || mydayview.date < Date(){
mydayview.layer.borderWidth = 0
}
}

Related

how to update TIME ZONE for using it in my calendar correctly?

Issue here is that while from API I get date in this form
Foundation.Date 2021-07-20 00:00:00 UTC
I successfully add hours, with I get start hour from API in form of "08:30:00" with gives me the value for start (but same issue about the end date) this way:
Foundation.Date 2021-07-20 08:30:00 UTC
but, when I get to calendar, the events are set to 10:30 AM, how could I correct the TIME ZONE?
I tested things like
let calendar = Calendar()
calendar.timezone = .current
but did not work
example from response
{
"data": {
"appointments": [
{
"date": "2021-07-20T00:00:00.000Z",
"time": {
"from": "08:30:00",
"to": "09:30:00"
}
}
]
}
}
my code
func onSynchronize(detailInfo: AppointmentDetail) {
let appointment = detailInfo
let fakeAddress = "fake address"
let fakeLocality = "Alderaan"
let store = EKEventStore()
store.requestAccess(to: .event) {(granted, error) in
if !granted { return }
let event = EKEvent(eventStore: store)
event.title = "my title"
guard let date0 = appointment.date else { return }
guard let hours = appointment.time else { return }
guard let host = appointment.host else { return }
if let componentsFrom = self.timeComponentsFromHourInString(from: hours.from) {
if let start = Calendar.current.date(byAdding: componentsFrom, to: date0, wrappingComponents: false) {
event.startDate = start
event.addAlarm(EKAlarm(absoluteDate: start.dayBefore))
event.addAlarm(EKAlarm(absoluteDate: start.halfHourBefore))
event.endDate = start.hourAfter
}
}
if let componentsTo = self.timeComponentsFromHourInString(from: hours.to) {
if let end = Calendar.current.date(byAdding: componentsTo, to: date0, wrappingComponents: false) {
event.endDate = end
}
}
event.location = fakeAddress.concats(fakeLocality, withSeparator: "-")
event.url = URL(string: BanksUtils.appLocalizeString(forKey: "url"))
if let managerDescription = host.managerDescription,
let manager = BanksUtils.localizeString(forKey: "handledBy").concats(managerDescription.capitalized),
let description = appointment.requestorDescription,
let reason = BanksUtils.localizeString(forKey: "reason").concats(description.capitalized) {
event.notes = manager + "\n" + reason
} else {
if let description = appointment.requestorDescription {
event.notes = BanksUtils.localizeString(forKey: "reason").concats(description.capitalized)
}
}
let structuredLocation = EKStructuredLocation(title: fakeAddress)
structuredLocation.geoLocation = self.location
event.structuredLocation = structuredLocation
event.calendar = store.defaultCalendarForNewEvents
do {
try store.save(event, span: .thisEvent, commit: true)
} catch {
Log.logger.error("Error: \(String(describing: error))")
}
guard let url = URL(string: "calshow:\(event.startDate.timeIntervalSinceReferenceDate)") else { return }
DispatchQueue.main.async {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
}
}
///Allows to get HH:MM:SS from an hour in form of a string
func timeComponentsFromHourInString(from string: String) -> DateComponents? {
let comps = string.components(separatedBy: ":")
guard comps.count == 3,
let hr = Int(comps[0]),
let mn = Int(comps[1]),
let sc = Int(comps[2])
else { return nil }
return DateComponents(hour: hr, minute: mn, second: sc)
}

local notification with repeats

I am making a local notification that will run every year, the problem is that I need notifications that come based on the Hebrew calendar, that is, July 20, 2020 according to the Hebrew calendar 28 tamuz 5780 and if we add the year to 28 tamuz 5781 then according to the Gregorian calendar comes out on July 1, 2021, that is, according to the Gregorian calendar, the date changes, I also need to take into account the leap year, AnniversariesReminderService is responsible for the notification, thanks
July 20, 2020 is 28 tamuz 5780
but
28 tamuz 5781 is July 1, 2021
I need to automatically calculate this time difference so that every year I receive a notification according to the Jewish date
struct ReminderAnniversaries {
var id:Int!
var description:String!
var date:Date!
}
class AnniversariesReminderService {
fileprivate var formatter :DateFormatter {
let dateformatterDay = DateFormatter()
dateformatterDay.dateFormat = "yyyy.MM.dd HH:mm"
return dateformatterDay
}
func scheduleReminder(data: ReminderAnniversaries, complited: (() -> Void)? = nil) {
removeScheduledReminder(data: data)
let request = self.prepareNotificationRequest(data: data)
UNUserNotificationCenter.current().add(request, withCompletionHandler: { error in
if error != nil {
print("ERROR SCHEDULE NOTIFICATION TYPE: \(String(describing: "\(data.id!)")), ERROR: \(String(describing:error?.localizedDescription))")
}
complited?()
})
}
fileprivate func prepareNotificationRequest(data: ReminderAnniversaries) -> UNNotificationRequest {
let content = UNMutableNotificationContent()
content.sound = .default
content.title = "AppDisplayName".localized()
content.body = data.description
let fireDate = data.date!
var dateInfo = DateComponents()
let triggerDaily = Calendar(identifier: .hebrew).dateComponents([.year, .month, .day, .hour, .second], from: fireDate)
dateInfo.year = fireDate.year
dateInfo.month = fireDate.month
dateInfo.day = fireDate.day
dateInfo.hour = fireDate.hour
dateInfo.minute = fireDate.minute + 1
dateInfo.second = fireDate.second
content.userInfo = ["id": data.id, "date" : fireDate,
"description": data.description]
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDaily, repeats: true)
let requestIdentifier = "\(data.id!)"
let request = UNNotificationRequest(identifier: requestIdentifier,
content: content, trigger: trigger)
print("NOTIFICATION SCHEDULED: (String(describing: requestIdentifier))")
print("NOTIFICATION TITLE: \(String(describing: content.body))")
print("NOTIFICATION TIME: \(String(describing: self.formatter.string(from: fireDate)))")
return request
}
func removeScheduledReminder(data: ReminderAnniversaries) {
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: ["\(data.id!)"])
print("NOTIFICATION REMOVED: \(String(describing: "\(data.id!)"))")
}
func getScheduledReminderDate(data: ReminderAnniversaries) -> String? {
var scheduledDate: Date?
let semaphore = DispatchSemaphore(value: 0)
UNUserNotificationCenter.current().getPendingNotificationRequests { notifications in
notifications.forEach({ notification in
if let scheduledType = notification.content.userInfo["id"] as? Int, scheduledType == data.id {
scheduledDate = notification.content.userInfo["date"] as? Date ?? Date()
// continue;
semaphore.signal()
}
})
if scheduledDate == nil {
semaphore.signal()
}
}
semaphore.wait()
return scheduledDate != nil ? formatter.string(from: scheduledDate!) : nil
}
}
Setting of date
#objc func doneDatePicker(){
if isAlarmClock && stage != 1 {
datePicker.datePickerMode = .dateAndTime
pickerDone.setTitle("Done".localized(), for: .normal)
pickerCancel.setTitle("Back".localized(), for: .normal)
stage = 1
formatter.dateFormat = "dd-MMM-yyyy HH:mm"
} else if !isAlarmClock {
//1
formatter.dateFormat = "dd-MMM-yyyy"
formatter.calendar = Calendar(identifier: .gregorian)
let dateOfDied = formatter.string(from: datePicker.date)
selectedDate = datePicker.date
// result Jule 21 2020 г.
//2
formatter.calendar = Calendar(identifier: .hebrew) //convert to jewish date
formatter.dateFormat = "dd-MMM-yyyy"
jewishDatePicker.date = datePicker.date
jewishDatePicker.calendar = NSCalendar(calendarIdentifier: NSCalendar.Identifier.hebrew)! as Calendar //convert to jewish calendar for adding year
//count of years between date of died and current date
let calendar = Calendar.current
// Replace the hour (time) of both dates with 00:00
let date1 = calendar.startOfDay(for: selectedDate)
let date2 = calendar.startOfDay(for: Date())
let components = calendar.dateComponents([.year], from: date1, to: date2)
var dayComponent = DateComponents()
dayComponent.year = components.year! + 1
let new_date = jewishDatePicker.calendar.date(byAdding: dayComponent, to: jewishDatePicker.date) // adding year by jewish calendar
jewishSelectedDate = new_date!
let hebDate = formatter.string(from: jewishSelectedDate)
jewishDatePicker.locale = Locale(identifier: "he")
jewishDatePicker.setDate(new_date!, animated: false)
print(jewishDatePicker.date)
// result Jule 9 2021 г.
//3
formatter.calendar = Calendar(identifier: .gregorian) //convert to gregorian date
let gregDate = formatter.string(from: new_date!)
// result Jule 09 2021 г.
alarmClock.isEnabled = true
alarmClockBtn()
var txt = Localized("You choosed", arguments: "\(dateOfDied)")
txt = txt + " " + "Jewish anniversary falls on".localized() + " " + "\(gregDate) (\(hebDate))," + " " + "select the date and time to remind you".localized()
text.text = txt
} else {
reminderTime = datePicker.date
pickerView.isHidden = true
}
}
#objc func addNotificationBtn(){
if !(name.text?.isEmpty ?? false) && !(parentName.text?.isEmpty ?? false) &&
jewishSelectedDate != nil && reminderTime != nil {
errorNotifier.notify("Done".localized(), title: "Notification configured".localized(), showOK: true) { [weak self] in
let remind = ReminderService()
var txt = Localized("You have set an anniversary reminder", arguments: self!.name.text!)
txt = txt + " " + "Бен(Бат)".localized() + " " + self!.parentName.text!
let data = ReminderAnniversaries(id: 11, description: txt, date: self?.reminderTime)
remind.anniversaries.scheduleReminder(data: data) {
print("ready")
}
self?.dismiss(animated: true, completion: nil)
}
} else if (name.text?.isEmpty ?? false) && (parentName.text?.isEmpty ?? false) {
errorNotifier.notify("Check the fields".localized(), title: "Fields must not be empty".localized(), showOK: true)
} else if jewishSelectedDate == nil {
errorNotifier.notify("Please select date if died".localized(), title:"", showOK: true)
} else if reminderTime == nil {
errorNotifier.notify("Please select a time for the anniversary reminder, the time is automatically set the day before the death anniversary".localized(), title: "Please select a time reminder".localized(), showOK: true)
}
}

FSCalendar check today date

How can I check that I clicked on today date?
https://github.com/WenchaoIOS/FSCalendar
I got the below output:
todaydateString = 2020-05-18
dateString = 2020-05-17
which is not matching:
import UIKit
class LoadViewExampleViewController: UIViewController, FSCalendarDataSource, FSCalendarDelegate {
private weak var calendar: FSCalendar!
fileprivate lazy var dateFormatter1: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
return formatter
}()
let dateString = "2020-05-15"
let dateString1 = "2020-05-16"
let dateString2 = "2020-05-13"
var selectedDates = NSMutableArray()
override func loadView() {
selectedDates = [dateString, dateString1, dateString2]
let view = UIView(frame: UIScreen.main.bounds)
view.backgroundColor = UIColor.groupTableViewBackground
self.view = view
let height: CGFloat = UIDevice.current.model.hasPrefix("iPad") ? 400 : 300
let calendar = FSCalendar(frame: CGRect(x: 0, y: self.navigationController!.navigationBar.frame.maxY, width: self.view.bounds.width, height: height))
calendar.dataSource = self
calendar.delegate = self
calendar.backgroundColor = UIColor.clear
calendar.appearance.todayColor = UIColor.gray
// calendar.appearance.borderDefaultColor = UIColor.black
//calendar.appearance.borderRadius = 0
self.view.addSubview(calendar)
self.calendar = calendar
}
func calendar(_ calendar: FSCalendar, didDeselect date: Date, at monthPosition: FSCalendarMonthPosition) {
let todaydate = Date()
let dateString = self.dateFormatter1.string(from: date)
let todaydateString = self.dateFormatter1.string(from: todaydate)
print("todaydateString = \(todaydateString)")
print("dateString = \(dateString)")
if dateString == todaydateString
{
print("GOOD")
}
}
func calendar(_ calendar: FSCalendar, imageFor date: Date) -> UIImage? {
let dateString = self.dateFormatter1.string(from: date)
if self.selectedDates.contains(dateString) {
let image : UIImage = UIImage(named: "checkbox_Tick")!
return image
}
return UIImage()
}
override func viewDidLoad() {
super.viewDidLoad()
self.title = "FSCalendar"
}
func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) {
if monthPosition == .previous || monthPosition == .next {
calendar.setCurrentPage(date, animated: true)
}
}
}

How to hide next day with FSCalendar based on week

Hi I want to hide the next business day, if user registration date and current date both are same. I need to hide next working day.
Sunday and Saturday are holidays.
I write code following if user is register on Friday I need to hide Monday, how to resolve this problem.
I write like this how to hide businessday
func calendar(_ calendar: FSCalendar, shouldSelect date: Date, at monthPosition: FSCalendarMonthPosition) -> Bool {
let joingdate = "2019-01-30" //modeldata.joindate
let currentdate = date.toString(dateFormat: "yyyy-MM-dd")
let currentDate = date
let currentdayweek = date.toString(dateFormat: "EEEE")
if joingdate == currentdate
{
if currentdayweek == "Friday"{
let businessday = Calendar.current.date(byAdding: .day, value: 3, to: currentDate)
return false
}
else if currentdayweek == "Saturday"{
let businessday = Calendar.current.date(byAdding: .day, value: 2, to: currentDate)
return false
}
else if currentdayweek == "Sunday"{
let businessday = Calendar.current.date(byAdding: .day, value: 1, to: currentDate)
return false
}
else
{
let businessday = Calendar.current.date(byAdding: .day, value: 1, to: currentDate)
return false
}
}
}
func minimumDate(for calendar: FSCalendar) -> Date {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let myString = formatter.string(from: Date())
let yourDate = formatter.date(from: myString)
formatter.dateFormat = "yyyy-MM-dd"
let strCurrentDate = formatter.string(from: yourDate!)
var addDay = 0
if let model = modeldata{
if let joiningdate = "2019-01-31"
{
if strCurrentDate == joiningdate
{
addDay = 2
}
let currentdayweek = yourDate!.toString(dateFormat: "EEEE")
if currentdayweek == "Friday"{
addDay = 4
}
else if currentdayweek == "Saturday"{
addDay = 3
}
else if currentdayweek == "Sunday"{
addDay = 2
}
}
}
let tomorrow = Calendar.current.date(byAdding:
.day, // updated this params to add hours
value: addDay,
to: formatter.date(from: strCurrentDate)!)
return tomorrow!
}
}

Apple Mach-O Linker Error (static, not ld)

I have recently encountered the Apple Mach-O Linker Error. Most guides suggest to change bitcode in Build Settings to "No", however it only applies to the ld error, which is different from mine. I will provide a screenshot, please help to fix the bug.
The pod HandySwift is causing the bugs to appear.
Here is the Github code source for it. https://github.com/Flinesoft/HandySwift
It is from the CSV Importer pod on Cocoapods.
https://cocoapods.org/pods/CSVImporter
Click here to look at the overview of the HandySwift files
Click here for the screenshot of the error
Code referencing the error:
"static (extension in HandySwift):Swift.Double.seconds(Swift.Double) -> Swift.Double", referenced from:
//
// CalendarViewController.swift
// DBS
//
// Created by SDG on 18/10/2017.
// Copyright © 2017 DBSSDG. All rights reserved.
//
import UIKit
import JTAppleCalendar
import CSVImporter
import SystemConfiguration
enum EventTypes{
case SE,PH,SH
}
struct events{
var Title : String
var StartDate : Date
var EndDate : Date
var EventType : EventTypes
}
var PassingEvent = ("G7-G11 Mid-year Exam (4-19)", Date(), Date(), EventTypes.SE)
var TodayEvent = [events] ()
extension Array where Element:Equatable {
func removeDuplicates() -> [Element] {
var result = [Element]()
for value in self {
if result.contains(value) == false {
result.append(value)
}
}
return result
}
}
class CalendarViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIViewControllerPreviewingDelegate {
#IBOutlet weak var CalendarView: JTAppleCalendarView!
#IBOutlet weak var CalendarStackView: UIStackView!
#IBOutlet weak var EventsTableView: UITableView!
#IBOutlet weak var StackView: UIStackView!
#IBOutlet weak var year: UILabel!
#IBOutlet weak var month: UILabel!
#IBOutlet weak var todayButton: UIButton!
var didScroll = false
#IBAction func TodayButton(_ sender: Any) {
CalendarView.scrollToDate(Date())
CalendarView.deselectAllDates()
CalendarView.selectDates([Date()])
EventsTableView.reloadData()
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(0.5), execute: {
self.CalendarView.selectDates([Date()])
self.EventsTableView.reloadData()
})
}
var index = 0
var CurrentDayEventsArray = [(Date, events)] ()
var CurrentDay = Date()
var DayEvents = [(Date, events)] ()
var SEBlue = UIColor(red: 97.0/255.0, green: 142.0/255.0, blue: 249.0/255.0, alpha: 1)
var SHOrange = UIColor(red: 1, green: 142.0/255.0, blue: 80.0/255.0, alpha: 1)
var currentmonth : String = ""
let formatter : DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.timeZone = Calendar.current.timeZone
dateFormatter.locale = Calendar.current.locale
dateFormatter.dateFormat = "yyyy MM dd"
return dateFormatter
}()
#IBOutlet weak var DaysStack: UIStackView!
func WillAddCalendar(acrion: UIAlertAction){
let StringURL = "https://calendar.google.com/calendar/ical/g.dbs.edu.hk_tdmjqqq8vlv8keepi7a65f7j7s%40group.calendar.google.com/public/basic.ics"
let url = URL(string: StringURL)!
if isInternetAvailable(){
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}else{
let networkAlert = UIAlertController(title: "ERROR", message: "Please check your network availability.", preferredStyle: .alert)
networkAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
present(networkAlert, animated: true)
}
}
func ShareCalendar(action: UIAlertAction){
let StringURL = "https://calendar.google.com/calendar/ical/g.dbs.edu.hk_tdmjqqq8vlv8keepi7a65f7j7s%40group.calendar.google.com/public/basic.ics"
let url = URL(string: StringURL)!
let ActivityController = UIActivityViewController(activityItems: [url], applicationActivities: nil)
present(ActivityController, animated: true, completion: nil)
}
func ActionSheetFunc(){
//Actions
let AddCalendarAction = UIAlertAction(title: "Add Calendar to Phone", style: .default, handler: WillAddCalendar)
let ShareAction = UIAlertAction(title: "Share Calendar", style: .default, handler: ShareCalendar)
let CancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
//Action Sheet
let ActionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
ActionSheet.addAction(AddCalendarAction)
ActionSheet.addAction(ShareAction)
ActionSheet.addAction(CancelAction)
present(ActionSheet, animated: true)
}
func AllEvents(){
performSegue(withIdentifier: "Calendar to All Events", sender: self)
}
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Calendar"
setUpCalendarView()
ParseCSV()
//UI Set up
year.frame = CGRect(x: 16, y: self.view.frame.height * 0.125, width: 100, height: 30)
todayButton.frame = CGRect(x: self.view.frame.width - todayButton.frame.size.width - 16, y: year.frame.origin.y, width: 0, height: 30)
todayButton.sizeToFit()
month.frame = CGRect(x: 16, y: year.frame.origin.y + year.frame.size.height, width: self.view.frame.width, height: 30)
CalendarView.frame.size.width = self.view.frame.width
CalendarView.frame.size.height = self.view.frame.height * 0.425
CalendarView.sizeToFit()
CalendarStackView.frame.origin.y = self.view.frame.height * 0.25
CalendarStackView.frame.origin.x = 0
CalendarStackView.frame.size.width = self.view.frame.width
CalendarStackView.frame.size.height = DaysStack.frame.height + CalendarView.frame.height
StackView.frame = CalendarStackView.frame
EventsTableView.frame.origin.y = CalendarStackView.frame.origin.y + CalendarStackView.frame.size.height
EventsTableView.frame.origin.x = 0
EventsTableView.frame.size.width = self.view.frame.width
EventsTableView.frame.size.height = self.view.frame.height - EventsTableView.frame.origin.y
EventsTableView.isScrollEnabled = true
self.registerForPreviewing(with: self, sourceView: EventsTableView)
//let EventsTableViewBottomConstraint = NSLayoutConstraint(item: EventsTableView, attribute: .bottomMargin, relatedBy: .equal, toItem: self.view, attribute: .bottomMargin, multiplier: 1, constant: 0)
//NSLayoutConstraint.activate([EventsTableViewBottomConstraint])
if #available(iOS 11.0, *) {
navigationItem.largeTitleDisplayMode = .never
}
EventsArray = [events]()
TodayEvent = [events]()
CurrentDayEventsArray = [(Date, events)]()
CalendarView.scrollToDate(Date())
TodayButton(self)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let AddCalendar = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(ActionSheetFunc))
let AllEvents = UIBarButtonItem(title: "All Events", style: .plain, target: self, action: #selector(self.AllEvents))
self.navigationItem.rightBarButtonItems = [AddCalendar, AllEvents]
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
CalendarView.selectDates([Date()])
}
func ParseCSV (){
let path = Bundle.main.path(forResource: "2017 - 2018 School Events New", ofType: "csv")!
let importer = CSVImporter<[String: String]>(path: path)
importer.startImportingRecords(structure: { (headerValues) -> Void in
}) { $0 }.onFinish { importedRecords in
for record in importedRecords {
self.formatter.dateFormat = "d/M/yyyy"
let EventStartDate = self.formatter.date(from: record["Start Date"]!)
let EventEndDate = self.formatter.date(from: record["End Date"]!)
let string = record["Title"]!
let input = string
var output = ""
var didColon = false
for i in input{
if didColon{
output += "\(i)"
}
if i == Character(":"){
didColon = true
}
}
output.removeFirst()
switch record["Type"]! {
case "PH" :
EventsArray += [events(Title: output, StartDate: EventStartDate!, EndDate: EventEndDate!, EventType: .PH)]
if EventStartDate! <= Date() && EventEndDate! >= Date(){
TodayEvent += [events(Title: output, StartDate: EventStartDate!, EndDate: EventEndDate!, EventType: .PH)]
}
case "SH" :
EventsArray += [events(Title: output, StartDate: EventStartDate!, EndDate: EventEndDate!, EventType: .SH)]
if EventStartDate! <= Date() && EventEndDate! >= Date(){
TodayEvent += [events(Title: output, StartDate: EventStartDate!, EndDate: EventEndDate!, EventType: .SH)]
}
case "SE" :
EventsArray += [events(Title: output, StartDate: EventStartDate!, EndDate: EventEndDate!, EventType: .SE)]
if EventStartDate! <= Date() && EventEndDate! >= Date(){
TodayEvent += [events(Title: output, StartDate: EventStartDate!, EndDate: EventEndDate!, EventType: .SE)]
}
default:
print("ERROR")
}
}
self.ParseAdoptionTimetable()
for i in TodayEvent{
self.CurrentDayEventsArray += [(Date(), i)]
}
self.EventsTableView.reloadData()
}
}
func ParseAdoptionTimetable(){
// if let url = URL(string: "http://www.dbs.edu.hk/index.php?section=calendar&listall=1") {
// do {
// let html = try String(contentsOf: url)
// for i in html.split(separator: ">") {
// if i.components(separatedBy: " adopts ").count == 2 {
// let String = (i.split(separator: "<")[0])
// print(String)
// //events(Title: i.split(separator: "<")[0], StartDate: <#T##Date#>, EndDate: <#T##Date#>, EventType: <#T##EventTypes#>)
// }
// }
// }catch{
// print("ERROR")
// }
// }
let Formatter = DateFormatter()
Formatter.dateFormat = "dd MM yyyy"
EventsArray += [events(Title: "30/4 Mon Adopts Tue Timetable", StartDate: Formatter.date(from: "30 04 2018")!, EndDate: Formatter.date(from: "30 04 2018")!, EventType: .SE), events(Title: "14/5 Mon Adopts Fri Timetable", StartDate: Formatter.date(from: "14 05 2018")!, EndDate: Formatter.date(from: "14 05 2018")!, EventType: .SE)]
EventsArray = EventsArray.sorted(by: { $0.StartDate <= $1.StartDate })
}
func setUpCalendarView(){
// Set up calendar spacing
CalendarView.minimumLineSpacing = 0
CalendarView.minimumInteritemSpacing = 0
// Set up labels
CalendarView.visibleDates{(visibleDates) in
let date = visibleDates.monthDates.first!.date
self.formatter.dateFormat = "yyyy"
self.year.text = self.formatter.string(from: date)
if self.year.text == self.formatter.string(from: Date()){
self.year.textColor = UIColor.red
} else {
self.year.textColor = UIColor.black
}
self.formatter.dateFormat = "MMMM"
self.month.text = self.formatter.string(from: date)
self.currentmonth = self.formatter.string(from: date)
if self.month.text == self.formatter.string(from: Date()){
self.month.textColor = UIColor.red
} else {
self.month.textColor = UIColor.black
}
}
}
func handleCellTextColor(view: JTAppleCell?, cellState: CellState) {
guard let validCell = view as? CustomCell else { return }
if cellState.isSelected {
validCell.selectedView.isHidden = false
} else {
validCell.selectedView.isHidden = true
}
}
func LoadEvents(view: JTAppleCell?, cellState: CellState) -> Any {
guard let validCell = view as? CustomCell else {return "Load Events Error"}
let CellDate = cellState.date
var CellDateEventsArray = [(Date, events)] ()
for event in EventsArray{
let EventStartDate = event.StartDate
let EventEndDate = event.EndDate
if CellDate >= EventStartDate && CellDate <= EventEndDate{
CellDateEventsArray += [(CellDate, event)]
}
}
CurrentDayEventsArray = CellDateEventsArray
if cellState.date == Date(){
self.EventsTableView.reloadData()
}
//CurrentDate = cellState.date
return CellDateEventsArray
}
func handleCellSelected(view: JTAppleCell?, cellState: CellState) {
guard let validCell = view as? CustomCell else { return }
var isPublicHoliday = false
for i in CurrentDayEventsArray{
if i.1.EventType == .PH{
isPublicHoliday = true
}
}
if cellState.isSelected {
validCell.datelabel.textColor = UIColor.white
}else{
if cellState.dateBelongsTo == .thisMonth{
//validCell.datelabel.textColor = UIColor.init(red: 253/255.0, green: 114/255.0, blue: 116.0/255.0, alpha: 1.0)
if cellState.day == .sunday || isPublicHoliday{
validCell.datelabel.textColor = UIColor.red
}else{
validCell.datelabel.textColor = UIColor.black
}
validCell.isUserInteractionEnabled = true
}else{
validCell.datelabel.textColor = UIColor.lightGray
//validCell.isUserInteractionEnabled = false
}
}
}
func setUpViewsForCalendar(from visibleDates: DateSegmentInfo){
let date = visibleDates.monthDates.first!.date
self.formatter.dateFormat = "yyyy"
self.year.text = self.formatter.string(from: date)
self.formatter.dateFormat = "MMMM"
self.month.text = self.formatter.string(from: date)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var count = 0
for _ in CurrentDayEventsArray{
count += 1
}
if count == 0{
return 1
}
return count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
DayEvents = CurrentDayEventsArray
let cell = tableView.dequeueReusableCell(withIdentifier: "CalendarEventCell")! as UITableViewCell
cell.isUserInteractionEnabled = true
if CurrentDayEventsArray.isEmpty{
cell.textLabel?.text = "No events"
cell.textLabel?.textAlignment = .center
cell.detailTextLabel?.text = ""
cell.imageView?.image = nil
cell.isUserInteractionEnabled = false
cell.accessoryType = .none
return cell
}
//Manage Date
let StartDate = CurrentDayEventsArray[indexPath.row].1.StartDate
let EndDate = CurrentDayEventsArray[indexPath.row].1.EndDate
self.formatter.dateFormat = "d/M"
let StartDateString = formatter.string(from: StartDate)
let EndDateString = formatter.string(from: EndDate)
//Image
let EventType = CurrentDayEventsArray[indexPath.row].1.EventType
if let image = UIImage(named: "dot"){
let tintableImage = image.withRenderingMode(.alwaysTemplate)
cell.imageView?.image = tintableImage
}
switch EventType {
case .PH:
cell.imageView?.tintColor = UIColor.red
case .SH:
cell.imageView?.tintColor = SHOrange
case .SE:
cell.imageView?.tintColor = SEBlue
default:
cell.imageView?.tintColor = UIColor.red
}
//Title
cell.textLabel?.adjustsFontSizeToFitWidth = true
cell.textLabel?.text = String(describing: CurrentDayEventsArray[indexPath.row].1.Title)
//Subtitle
let Subtitle = "\(StartDateString) - \(EndDateString)"
if StartDate != EndDate{
cell.detailTextLabel?.text = Subtitle
}else{
cell.detailTextLabel?.text = StartDateString
}
//Arrow
cell.accessoryType = UITableViewCellAccessoryType.disclosureIndicator
//cell.selectionStyle = .gray
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
index = indexPath.row
PassingEvent = (DayEvents[index].1.Title, DayEvents[index].1.StartDate, DayEvents[index].1.EndDate, DayEvents[index].1.EventType)
performSegue(withIdentifier: "Detail Event", sender: self)
}
/*
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let DestViewController = segue.destination as! DetailedEventViewController
DestViewController.PassingEvent = (CurrentDayEventsArray[index].1.Title, CurrentDayEventsArray[index].1.StartDate, CurrentDayEventsArray[index].1.EndDate, CurrentDayEventsArray[index].1.EventType)
}
*/
public func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
guard let indexPath = EventsTableView.indexPathForRow(at: location) else {
return nil
}
previewingContext.sourceRect = EventsTableView.cellForRow(at: indexPath)!.frame
let index = indexPath.row
PassingEvent = (DayEvents[index].1.Title, DayEvents[index].1.StartDate, DayEvents[index].1.EndDate, DayEvents[index].1.EventType)
let destViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Detail Event") as! DetailedEventViewController
return destViewController
return nil
}
public func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
navigationController?.pushViewController(viewControllerToCommit, animated: true)
}
func isInternetAvailable() -> Bool {
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)
let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
}
}
var flags = SCNetworkReachabilityFlags()
if !SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) {
return false
}
let isReachable = flags.contains(.reachable)
let needsConnection = flags.contains(.connectionRequired)
return (isReachable && !needsConnection)
}
}
extension CalendarViewController: JTAppleCalendarViewDelegate, JTAppleCalendarViewDataSource {
func calendar(_ calendar: JTAppleCalendarView, willDisplay cell: JTAppleCell, forItemAt date: Date, cellState: CellState, indexPath: IndexPath) {
EventsTableView.reloadData()
}
func configureCalendar(_ calendar: JTAppleCalendarView) -> ConfigurationParameters {
formatter.dateFormat = "yyy MM dd"
formatter.timeZone = Calendar.current.timeZone
formatter.locale = Calendar.current.locale
let startDate = formatter.date(from: "2017 09 01")
let endDate = formatter.date(from: "2019 08 31")
let generateInDates: InDateCellGeneration = .forAllMonths
let generateOutDates: OutDateCellGeneration = .tillEndOfGrid
let firstDayOfWeek: DaysOfWeek = .sunday
let parameters = ConfigurationParameters(startDate: startDate!, endDate: endDate!, numberOfRows: 4, calendar: Calendar.current, generateInDates: generateInDates, generateOutDates: generateOutDates, firstDayOfWeek: firstDayOfWeek, hasStrictBoundaries: true)
//let parameters = ConfigurationParameters(startDate: startDate!, endDate: endDate!)
return parameters
}
func calendar(_ calendar: JTAppleCalendarView, cellForItemAt date: Date, cellState: CellState, indexPath: IndexPath) -> JTAppleCell {
let CalendarCell = calendar.dequeueReusableJTAppleCell(withReuseIdentifier: "CustomCell", for: indexPath) as! CustomCell
CalendarCell.datelabel.text = cellState.text
CalendarCell.selectedView.layer.cornerRadius = CalendarCell.selectedView.frame.width/2
CalendarCell.backgroundColor = UIColor.white
CalendarCell.EventCircle.layer.cornerRadius = CalendarCell.EventCircle.frame.width / 2
CalendarCell.EventCircle.isHidden = true
CalendarCell.SchoolHolidayBar.backgroundColor = self.SHOrange
CalendarCell.SchoolHolidayBar.isHidden = true
CalendarCell.isUserInteractionEnabled = false
if cellState.dateBelongsTo == .thisMonth{
CalendarCell.isSelected = false
}
LoadEvents(view: CalendarCell, cellState: cellState)
for i in CurrentDayEventsArray{
if i.1.EventType == .SH{
CalendarCell.SchoolHolidayBar.isHidden = true
CalendarCell.EventCircle.backgroundColor = SHOrange
CalendarCell.EventCircle.isHidden = false
break
}else if i.1.EventType == .PH{
CalendarCell.datelabel.textColor = UIColor.red
}else if i.1.EventType == .SE{
CalendarCell.EventCircle.backgroundColor = UIColor.lightGray
CalendarCell.EventCircle.isHidden = false
}else{
}
}
if cellState.date == Date(){
LoadEvents(view: CalendarCell, cellState: cellState)
EventsTableView.reloadData()
}
handleCellTextColor(view: CalendarCell, cellState: cellState)
handleCellSelected(view: CalendarCell, cellState: cellState)
return CalendarCell
}
func calendar(_ calendar: JTAppleCalendarView, didSelectDate date: Date, cell: JTAppleCell?, cellState: CellState) {
if didScroll{
calendar.deselect(dates: [CurrentDay])
didScroll = false
}
CurrentDay = date
//calendar.deselectAllDates()
//calendar.selectDates([date])
handleCellTextColor(view: cell, cellState: cellState)
handleCellSelected(view: cell, cellState: cellState)
LoadEvents(view: cell, cellState: cellState)
EventsTableView.reloadData()
}
func calendar(_ calendar: JTAppleCalendarView, didDeselectDate date: Date, cell: JTAppleCell?, cellState: CellState) {
handleCellTextColor(view: cell, cellState: cellState)
handleCellSelected(view: cell, cellState: cellState)
//calendar.deselect(dates: [date])
}
func calendar(_ calendar: JTAppleCalendarView, didScrollToDateSegmentWith visibleDates: DateSegmentInfo) {
let date = visibleDates.monthDates.first!.date
formatter.dateFormat = "yyyy"
year.text = self.formatter.string(from: date)
formatter.dateFormat = "MMMM"
month.text = self.formatter.string(from: date)
setUpCalendarView()
}
func calendarDidScroll(_ calendar: JTAppleCalendarView) {
didScroll = true
}
}
//}
In your TodayButton(_:) instead of:
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(0.5), execute: {
//...
})
do:
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
//...
})
That .seconds(Int) takes an Int. So passing a Double in it by doing .seconds(0.5) makes it ambiguous as there is no .seconds(Double) in the DispatchTimeInterval enum.
To achieve this 0.5 second delay you can either do it in 2 ways:
+ 0.5
+ .milliseconds(500)