使用内置iOS日历在swift/Access中以编程方式创建日历

使用内置iOS日历在swift/Access中以编程方式创建日历,ios,swift,uikit,eventkit,Ios,Swift,Uikit,Eventkit,我正在尝试在我的应用程序中创建一个自定义日历,并找到了一个关于构建自定义日历的教程(),我在一个新项目中遵循了该教程,它成功了。但是,本教程使用故事板,而我的应用程序不使用。因此,我尝试使用子视图将情节提要UI设置迁移到代码中,但没有成功 该功能的目的是在日历中存储业务会议,我愿意放弃自定义日历功能并访问iOS日历,但我不确定如何做到这一点 尝试运行此操作时遇到的错误是线程1:致命错误:在view.addSubview(calendarView)中展开可选值时意外发现nil 该应用程序使用Tab

我正在尝试在我的应用程序中创建一个自定义日历,并找到了一个关于构建自定义日历的教程(),我在一个新项目中遵循了该教程,它成功了。但是,本教程使用故事板,而我的应用程序不使用。因此,我尝试使用子视图将情节提要UI设置迁移到代码中,但没有成功

该功能的目的是在日历中存储业务会议,我愿意放弃自定义日历功能并访问iOS日历,但我不确定如何做到这一点

尝试运行此操作时遇到的错误是线程1:致命错误:在view.addSubview(calendarView)中展开可选值时意外发现nil

该应用程序使用TabBarController进行导航,Organizer是我的选项卡之一

任何关于定制日历工作的帮助,或者我可以使用什么代码访问iOS日历的帮助,都将不胜感激

代码如下

import UIKit
import JTAppleCalendar
import EventKit
class Organiser: UIViewController {

var calendarView: JTAppleCalendarView!
var year: UILabel!
var month: UILabel!

let outsideMonthColour = UIColor.white
let monthColour = UIColor.black
let selectedMonthColour = UIColor.red
let currentDateSelectedColour = UIColor.blue


let formatter = DateFormatter()

override func viewDidLoad() {
    super.viewDidLoad()

    view.addSubview(calendarView)
    view.addSubview(year)
    view.addSubview(month)


    calendarView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive=true
    calendarView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive=true
    calendarView.heightAnchor.constraint(equalToConstant: 200)
    calendarView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: -30)

    month.bottomAnchor.constraint(equalTo: calendarView.topAnchor, constant: 25)
    month.leftAnchor.constraint(equalTo: calendarView.leftAnchor, constant: 0)


    year.bottomAnchor.constraint(equalTo: month.topAnchor, constant: 25)
    year.leftAnchor.constraint(equalTo: month.leftAnchor, constant: 25)

    calendarView.translatesAutoresizingMaskIntoConstraints = false
    month.translatesAutoresizingMaskIntoConstraints = false
    year.translatesAutoresizingMaskIntoConstraints = false

    // Do any additional setup after loading the view, typically from a nib.
}


//setup calendar cells
func setupCalendarView(){
    calendarView.minimumLineSpacing = 0
    calendarView.minimumInteritemSpacing = 0

    calendarView.visibleDates { visibleDates in
        self.setupViewsOfCalendar(from: visibleDates)
    }
}

//setup selected cell text colour function
func handleCellTextColour(view: JTAppleCell?, cellState: CellState){
    guard let validCell = view as? CustomCell else { return }

    if cellState.isSelected {
        validCell.dateLabel?.textColor = currentDateSelectedColour
    } else {
        if cellState.dateBelongsTo == .thisMonth {
            validCell.dateLabel?.textColor = monthColour
        } else {
            validCell.dateLabel?.textColor = outsideMonthColour
        }
    }

}

//setup selected cell highlight function
func handleCellSelected(view: JTAppleCell?, cellState: CellState){
    guard let validCell = view as? CustomCell else { return }

    if cellState.isSelected {
        validCell.selectedView?.isHidden = false
    } else {
        validCell.selectedView?.isHidden = true
    }
}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


}


extension Organiser: JTAppleCalendarViewDataSource{
func configureCalendar(_ calendar: JTAppleCalendarView) -> ConfigurationParameters {
    formatter.dateFormat = "yyyy mm dd"
    formatter.timeZone = Calendar.current.timeZone
    formatter.locale = Calendar.current.locale

    let startDate = formatter.date(from: "2017 01 01")
    let endDate = formatter.date(from: "2018 12 31")

    let parameters = ConfigurationParameters(startDate: startDate!, endDate: endDate!)
    return parameters
}

}


extension Organiser: JTAppleCalendarViewDelegate{

func calendar(_ calendar: JTAppleCalendarView, willDisplay cell: JTAppleCell, forItemAt date: Date, cellState: CellState, indexPath: IndexPath) {
    let myCustomCell = calendar.dequeueReusableJTAppleCell(withReuseIdentifier: "CustomCell", for: indexPath) as! CustomCell
    myCustomCell.dateLabel?.text = cellState.text

    handleCellSelected(view: cell, cellState: cellState)
    handleCellTextColour(view: cell, cellState: cellState)
    return ()
}

func calendar(_ calendar: JTAppleCalendarView, cellForItemAt date: Date, cellState: CellState, indexPath: IndexPath) -> JTAppleCell {
    let myCustomCell = calendar.dequeueReusableJTAppleCell(withReuseIdentifier: "CustomCell", for: indexPath) as! CustomCell
    self.calendar(calendar, willDisplay: myCustomCell, forItemAt: date, cellState: cellState, indexPath: indexPath)
    myCustomCell.dateLabel?.text = cellState.text
    return myCustomCell
}
//function for handling interface changes when cell selected
func calendar(_ calendar: JTAppleCalendarView, didSelectDate date: Date, cell: JTAppleCell?, cellState: CellState) {
    handleCellSelected(view: cell, cellState: cellState)
    handleCellTextColour(view: cell, cellState: cellState)
}
//function for handling interface changes when cell deselected selected
func calendar(_ calendar: JTAppleCalendarView, didDeselectDate date: Date, cell: JTAppleCell?, cellState: CellState) {
    handleCellSelected(view: cell, cellState: cellState)
    handleCellTextColour(view: cell, cellState: cellState)
}
//function so that month and year show when calendar loads
func setupViewsOfCalendar(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)
}

//function to change month when calendar scrolled
func calendar(_ calendar: JTAppleCalendarView, didScrollToDateSegmentWith visibleDates: DateSegmentInfo) {
    let date = visibleDates.monthDates.first!.date

    formatter.dateFormat = "yyyy"
    year.text = formatter.string(from: date)

    formatter.dateFormat = "MMMM"
    month.text = formatter.string(from: date)
}

}

您遇到的崩溃是因为您没有初始化JTAppleCalendarView,因此当您尝试将其添加为子视图时,它为零。编译器不会抱怨,因为您在声明中强制展开它

替换

var calendarView: JTAppleCalendarView!

请注意,当您尝试将年和月标签添加为子视图时,在接下来的两行中,您也会因为同样的原因而崩溃

您可以将其声明替换为:

let year = UILabel()
let month = UILabel()

您正在使用“!”强制展开JTAppleClendar的实例。因此,如果值为零,则强制展开时,应用程序将崩溃。要避免同样的情况,您需要遵循以下步骤

步骤1:您可以将中的对象库中的UIView添加到xib或情节提要中

步骤2:然后需要在Identity Inspector中设置JTAppleCalendarView,如下图所示

然后,您可以使用与您使用的代码相同的代码,并且它不会崩溃


注意:您还需要将其添加到UILabel中,以避免UILabel崩溃。

在您的xib中,您是否连接了FTAppleCalendarView和UILabels?如果您已连接,则不会发生崩溃。感谢您的帮助,但我正在尝试使用代码来构建我的应用程序-而不是故事板或xib文件谢谢!这是有道理的,我现在可以构建并运行应用程序,但当我的应用程序运行时,视图控制器“Organizer”仍然为空。要使日历可见,我还缺少其他内容吗?我已编辑了约束,以包括TranslatesAutoResizengMaskinToConstraints和添加calendarView约束,但它仍然没有显示您对约束代码有问题。isActive=true仅设置在前两个选项上。乘数设置为-30表示宽度计算为view.width*-30。因此,如果视图宽度为100pt,日历宽度将为-3000。月份和年份标签也没有宽度/高度限制
let year = UILabel()
let month = UILabel()