我已经以编程方式初始化了第一个视图控制器以显示日历。我使用下面的gitHub文件中的代码显示日历: https://github.com/Akhilendra/calenderAppiOS
我对代码进行了一些更改,以删除更改颜色的功能,并将导航栏按钮“主题”替换为标有“历史记录”的按钮。 我还在Main.storyboard上创建了navigationController和ViewController。我还已经将ViewController storyBoard对象链接到ViewController类。 在链接的项目中,当您单击日期时,该特定单元格会更改颜色。但是在我的项目中,单击日期时,我希望将用户转到显示日期的下一个屏幕(在其他功能中,我想执行的操作)。
日历的didSelectItem()函数位于名为CalendarView的类中。这里的问题是,由于navigationController是UIViewController类的对象,因此无法访问此类中的navigationController.pushViewController()。
我尝试创建firstViewController类的实例,并在该实例上使用pushViewController,但这没有用。 该项目运行正常,并且显示了日历并选择了单元格。唯一的问题是不会出现下一个屏幕。
//视图控制器:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
//Title for the view:
self.title = "My Calendar"
//Month-year will be displayed if this property is set to false:
self.navigationController?.navigationBar.isTranslucent=false
//Bg colour of the entire view:
self.view.backgroundColor=UIColor.white
//Add the subview that contains the calendar:
view.addSubview(calendarView)
//Constraints for the calendar:
calendarView.topAnchor.constraint(equalTo: view.topAnchor, constant: 10).isActive=true
calendarView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -12).isActive=true
calendarView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 12).isActive=true
calendarView.heightAnchor.constraint(equalToConstant: 365).isActive=true
//The left bar button on navigation controller:
let leftBarBtn = UIBarButtonItem(title: "History", style: .plain, target: self, action: #selector(leftBarBtnAction))
self.navigationItem.leftBarButtonItem = leftBarBtn
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
calendarView.myCollectionView.collectionViewLayout.invalidateLayout()
}
//Defines what happens when left bar button is clicked:
@objc func leftBarBtnAction(sender: UIBarButtonItem) {
print("History")
}
//Object of type CalendarView:
let calendarView: CalendarView = {
let v=CalendarView()
v.translatesAutoresizingMaskIntoConstraints=false
return v
}()
}
// CalendarView类:
class CalendarView: UIView, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, MonthViewDelegate {
var numOfDaysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31]
var currentMonthIndex: Int = 0
var currentYear: Int = 0
var presentMonthIndex = 0
var presentYear = 0
var todaysDate = 0
var firstWeekDayOfMonth = 0 //(Sunday-Saturday 1-7)
override init(frame: CGRect) {
super.init(frame: frame)
initializeView()
}
func changeTheme() {
myCollectionView.reloadData()
monthView.lblName.textColor = UIColor.blue
//Colour of the button for the next month:
monthView.btnRight.setTitleColor(UIColor.blue, for: .normal)
//Colour of the button for the previous month:
monthView.btnLeft.setTitleColor(UIColor.blue, for: .normal)
for i in 0..<7 {
(weekdaysView.myStackView.subviews[i] as! UILabel).textColor = UIColor.blue
}
}
func initializeView() {
currentMonthIndex = Calendar.current.component(.month, from: Date())
currentYear = Calendar.current.component(.year, from: Date())
todaysDate = Calendar.current.component(.day, from: Date())
firstWeekDayOfMonth=getFirstWeekDay()
//for leap years, make february month of 29 days
if currentMonthIndex == 2 && currentYear % 4 == 0 {
numOfDaysInMonth[currentMonthIndex-1] = 29
}
//end
presentMonthIndex=currentMonthIndex
presentYear=currentYear
setupViews()
myCollectionView.delegate=self
myCollectionView.dataSource=self
myCollectionView.register(dateCVCell.self, forCellWithReuseIdentifier: "Cell")
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return numOfDaysInMonth[currentMonthIndex-1] + firstWeekDayOfMonth - 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell=collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! dateCVCell
//cell.backgroundColor=UIColor.clear
if indexPath.item <= firstWeekDayOfMonth - 2 {
cell.isHidden=true
} else {
let calcDate = indexPath.row-firstWeekDayOfMonth+2
cell.isHidden=false
cell.lbl.text="\(calcDate)"
if calcDate < todaysDate && currentYear == presentYear && currentMonthIndex == presentMonthIndex {
//Disable user interaction on past dates
cell.isUserInteractionEnabled=false
//Colour of the text in past date cells
cell.lbl.textColor = UIColor.lightGray
} else {
//Enable user interaction on upcoming dates
cell.isUserInteractionEnabled=true
//Colour of the text in upcoming date cells
cell.lbl.textColor = UIColor.blue
}
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell=collectionView.cellForItem(at: indexPath)
//Print the selected date:
let lbl = cell?.subviews[1] as! UILabel
print(lbl.text!)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = collectionView.frame.width/7 - 8
let height: CGFloat = 40
return CGSize(width: width, height: height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 8.0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 8.0
}
func getFirstWeekDay() -> Int {
let day = ("\(currentYear)-\(currentMonthIndex)-01".date?.firstDayOfTheMonth.weekday)!
//return day == 7 ? 1 : day
return day
}
func didChangeMonth(monthIndex: Int, year: Int) {
currentMonthIndex=monthIndex+1
currentYear = year
//for leap year, make february month of 29 days
if monthIndex == 1 {
if currentYear % 4 == 0 {
numOfDaysInMonth[monthIndex] = 29
} else {
numOfDaysInMonth[monthIndex] = 28
}
}
//end
firstWeekDayOfMonth=getFirstWeekDay()
myCollectionView.reloadData()
monthView.btnLeft.isEnabled = !(currentMonthIndex == presentMonthIndex && currentYear == presentYear)
}
func setupViews() {
addSubview(monthView)
monthView.topAnchor.constraint(equalTo: topAnchor).isActive=true
monthView.leftAnchor.constraint(equalTo: leftAnchor).isActive=true
monthView.rightAnchor.constraint(equalTo: rightAnchor).isActive=true
monthView.heightAnchor.constraint(equalToConstant: 35).isActive=true
monthView.delegate=self
addSubview(weekdaysView)
weekdaysView.topAnchor.constraint(equalTo: monthView.bottomAnchor).isActive=true
weekdaysView.leftAnchor.constraint(equalTo: leftAnchor).isActive=true
weekdaysView.rightAnchor.constraint(equalTo: rightAnchor).isActive=true
weekdaysView.heightAnchor.constraint(equalToConstant: 30).isActive=true
addSubview(myCollectionView)
myCollectionView.topAnchor.constraint(equalTo: weekdaysView.bottomAnchor, constant: 0).isActive=true
myCollectionView.leftAnchor.constraint(equalTo: leftAnchor, constant: 0).isActive=true
myCollectionView.rightAnchor.constraint(equalTo: rightAnchor, constant: 0).isActive=true
myCollectionView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive=true
}
let monthView: MonthView = {
let v=MonthView()
v.translatesAutoresizingMaskIntoConstraints=false
return v
}()
let weekdaysView: WeekdaysView = {
let v=WeekdaysView()
v.translatesAutoresizingMaskIntoConstraints=false
return v
}()
let myCollectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
let myCollectionView=UICollectionView(frame: CGRect.zero, collectionViewLayout: layout)
myCollectionView.showsHorizontalScrollIndicator = false
myCollectionView.translatesAutoresizingMaskIntoConstraints=false
myCollectionView.backgroundColor=UIColor.clear
myCollectionView.allowsMultipleSelection=false
return myCollectionView
}()
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class dateCVCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor=UIColor.clear
layer.cornerRadius=5
layer.masksToBounds=true
setupViews()
}
func setupViews() {
addSubview(lbl)
lbl.topAnchor.constraint(equalTo: topAnchor).isActive=true
lbl.leftAnchor.constraint(equalTo: leftAnchor).isActive=true
lbl.rightAnchor.constraint(equalTo: rightAnchor).isActive=true
lbl.bottomAnchor.constraint(equalTo: bottomAnchor).isActive=true
}
let lbl: UILabel = {
let label = UILabel()
label.text = "00"
label.textAlignment = .center
label.font=UIFont.systemFont(ofSize: 16)
label.textColor=UIColor.darkGray
label.translatesAutoresizingMaskIntoConstraints=false
return label
}()
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
//get first day of the month
extension Date {
var weekday: Int {
return Calendar.current.component(.weekday, from: self)
}
var firstDayOfTheMonth: Date {
return Calendar.current.date(from: Calendar.current.dateComponents([.year,.month], from: self))!
}
}
//get date from string
extension String {
static var dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
return formatter
}()
var date: Date? {
return String.dateFormatter.date(from: self)
}
}
// MonthView类:
// The protocol with didChangeMonth function:
protocol MonthViewDelegate: class {
func didChangeMonth(monthIndex: Int, year: Int)
}
class MonthView: UIView {
//The array that contains the name of the months:
var monthsArr = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
//Index of the current month:
var currentMonthIndex = 0
//Index of the current year:
var currentYear: Int = 0
//Define an object of the protocol MonthViewDelegate:
var delegate: MonthViewDelegate?
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor=UIColor.clear
//Index of the current month:
currentMonthIndex = Calendar.current.component(.month, from: Date()) - 1
//Index of the current year:
currentYear = Calendar.current.component(.year, from: Date())
setupViews()
//Disable the previous month button on launch:
btnLeft.isEnabled=false
}
//Change the number of days in a month(next/previous):
@objc func btnLeftRightAction(sender: UIButton) {
//When next month button is clicked:
if sender == btnRight {
//Increment the index of the current month:
currentMonthIndex += 1
//Check if next month is January of the next year:
if currentMonthIndex > 11 {
//Reset the current month index:
currentMonthIndex = 0
//Increment the current year:
currentYear += 1
}
}
//When previous month button is clicked:
else {
//Decrement the index of the current month:
currentMonthIndex -= 1
//Check if previous month is December of the last year:
if currentMonthIndex < 0 {
//Reset the current month index:
currentMonthIndex = 11
//Decrement the current year:
currentYear -= 1
}
}
// Set label text for Month-Year:
lblName.text="\(monthsArr[currentMonthIndex]) \(currentYear)"
//Call didChangeMonth on delegate object:
delegate?.didChangeMonth(monthIndex: currentMonthIndex, year: currentYear)
}
func setupViews() {
//Add label 'Month-Year'
self.addSubview(lblName)
//Constraints for label Month-Year:
lblName.topAnchor.constraint(equalTo: topAnchor).isActive=true
lblName.centerXAnchor.constraint(equalTo: centerXAnchor).isActive=true
lblName.widthAnchor.constraint(equalToConstant: 150).isActive=true
lblName.heightAnchor.constraint(equalTo: heightAnchor).isActive=true
//Set label text for Month-Year:
lblName.text="\(monthsArr[currentMonthIndex]) \(currentYear)"
//Add view for 'next month' button:
self.addSubview(btnRight)
//Constraints for 'next month' button:
btnRight.topAnchor.constraint(equalTo: topAnchor).isActive=true
btnRight.rightAnchor.constraint(equalTo: rightAnchor).isActive=true
btnRight.widthAnchor.constraint(equalToConstant: 50).isActive=true
btnRight.heightAnchor.constraint(equalTo: heightAnchor).isActive=true
//Add view for 'previous month' button:
self.addSubview(btnLeft)
btnLeft.topAnchor.constraint(equalTo: topAnchor).isActive=true
btnLeft.leftAnchor.constraint(equalTo: leftAnchor).isActive=true
btnLeft.widthAnchor.constraint(equalToConstant: 50).isActive=true
btnLeft.heightAnchor.constraint(equalTo: heightAnchor).isActive=true
}
//The label that displays Month-year
let lblName: UILabel = {
let lbl=UILabel()
//Default text for month and year:
lbl.text="Default Month Year text"
//Colour of month and year:
lbl.textColor = UIColor.blue
//Alignment of month and year:
lbl.textAlignment = .center
//Font size and style of month and year:
lbl.font=UIFont.boldSystemFont(ofSize: 16)
lbl.translatesAutoresizingMaskIntoConstraints=false
return lbl
}()
//Button for next month:
let btnRight: UIButton = {
let btn=UIButton()
//Title for next month button:
btn.setTitle(">", for: .normal)
//Title colour of next month button:
btn.setTitleColor(UIColor.blue, for: .normal)
btn.translatesAutoresizingMaskIntoConstraints=false
//Function on next month button click:
btn.addTarget(self, action: #selector(btnLeftRightAction(sender:)), for: .touchUpInside)
return btn
}()
//Button for previous month:
let btnLeft: UIButton = {
let btn=UIButton()
//Title for previous month button:
btn.setTitle("<", for: .normal)
//Title colour for previous month button when enabled:
btn.setTitleColor(UIColor.blue, for: .normal)
btn.translatesAutoresizingMaskIntoConstraints=false
//Function on previous month button click:
btn.addTarget(self, action: #selector(btnLeftRightAction(sender:)), for: .touchUpInside)
//Title colour of the previous button when disabled:
btn.setTitleColor(UIColor.lightGray, for: .disabled)
return btn
}()
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
// WeekdaysView类:
class WeekdaysView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor=UIColor.clear
setupViews()
}
func setupViews() {
addSubview(myStackView)
myStackView.topAnchor.constraint(equalTo: topAnchor).isActive=true
myStackView.leftAnchor.constraint(equalTo: leftAnchor).isActive=true
myStackView.rightAnchor.constraint(equalTo: rightAnchor).isActive=true
myStackView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive=true
//Array that contains name of the days in a week:
var daysArr = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]
//Iteration for the properties of each day in a week:
for i in 0..<7 {
let lbl=UILabel()
//Text in the label for weekdays:
lbl.text=daysArr[i]
//Alignment of the text in week day label:
lbl.textAlignment = .center
//Colour of the label for weekdays:
lbl.textColor = UIColor.blue
//Stack that contains all labels with weekday names:
myStackView.addArrangedSubview(lbl)
}
}
//The stack that will contain the names of the days in a week:
let myStackView: UIStackView = {
let stackView=UIStackView()
//Distribute the labels as:
stackView.distribution = .fillEqually
stackView.translatesAutoresizingMaskIntoConstraints=false
return stackView
}()
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
答案 0 :(得分:0)
您可以定义委托协议。例如:HandleDateTransfer
。
使用该功能定义协议。例如setDate()
。
向CalendarView
类添加一个弱的委托属性。
弱var dateTransferdelegate:HandleDateTransfer?
将委托附加到CalendarView
类。
符合协议,并在要设置日期的函数中实现setDate()
方法。
在setDate()
函数内调用didSelectItemAt
方法。
答案 1 :(得分:0)
使用与didChangeMonth
功能相同的委托/协议模式。
基本上,创建一个新协议:
// The protocol with didSelectDate function:
protocol SelectDateDelegate: class {
func didSelectDate(dayIndex: Int, monthIndex: Int, year: Int)
}
让ViewController符合该协议
class ViewController: UIViewController, SelectDateDelegate {
override func viewDidLoad() {
// as normal ...
view.addSubview(calendarView)
// set the new delegate
calendarView.delegate = self
}
func didSelectDate(dayIndex: Int, monthIndex: Int, year: Int) {
let vc = DateDetailViewController()
vc.dateData = dayIndex // or however you're managing the data
self.navigationController?.pushViewController(vc, animated: true)
}
}
然后在CalendarView
类中:
var delegate: SelectDateDelegate?
和didSelectItemAt
中的
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell=collectionView.cellForItem(at: indexPath)
//Print the selected date:
let lbl = cell?.subviews[1] as! UILabel
print(lbl.text!)
// whatever variables / properties you're using to track day / month / year
delegate?.didSelectDate(dayIndex: dayVal, monthIndex: monthVal, year: yearVal)
}