Swift FSCalendar 在表格视图的日历显示事件中选择日期

Posted

技术标签:

【中文标题】Swift FSCalendar 在表格视图的日历显示事件中选择日期【英文标题】:Swift FSCalendar select date in calendar display event in tableview 【发布时间】:2020-12-09 18:40:19 【问题描述】:

我正在为我的应用程序使用 FSCalendar。我需要帮助在我的日历中列出我的收藏视图中的特定事件并显示在它下面的表格视图中。因此,当用户单击日历上的单元格(即日期)时。表格视图将更新并显示当天的特定事件。我已经检查了相关文档,但没有针对此特定任务的文档,并且我查看了其他几个地方。我将不胜感激一些代码示例,因为我对使用 FSCalendar 并实现它非常陌生。谢谢

我当前的应用页面:

我的一些相关代码:

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, FSCalendarDelegate, FSCalendarDataSource, FSCalendarDelegateAppearance, UIGestureRecognizerDelegate 

    
    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var calendar: FSCalendar!
    @IBOutlet weak var animationSwitch: UISwitch!
    @IBOutlet weak var calendarHeightConstraint: NSLayoutConstraint!

    
    fileprivate let gregorian: Calendar = Calendar(identifier: .gregorian)
    
    var datesWithEvent = ["2020-12-23","2020-12-16","2020-12-18","2020-12-14","2020-12-06"]
    var datesWithMultipleEvents = ["2020-12-03","2020-12-13","2020-12-11","2020-10-03","2020-12-06"]
    
    fileprivate lazy var dateFormatter2: DateFormatter = 
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd"
        return formatter
    ()

override func viewDidLoad() 
        super.viewDidLoad()
        
        calendar.select(Date())
        
        self.view.addGestureRecognizer(self.scopeGesture)
        self.tableView.panGestureRecognizer.require(toFail: self.scopeGesture)
        calendar.scope = .week
//        calendar.scrollDirection = .horizontal
        calendar.accessibilityIdentifier = "calendar"

    

func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) 
        print("did select date \(self.dateFormatter2.string(from: date))")
        let selectedDates = calendar.selectedDates.map(self.dateFormatter2.string(from: $0))
        print("selected dates is \(selectedDates)")
        if monthPosition == .next || monthPosition == .previous 
            calendar.setCurrentPage(date, animated: true)
        
    
    
    
    func calendarCurrentPageDidChange(_ calendar: FSCalendar) 
        print("\(self.dateFormatter2.string(from: calendar.currentPage))")
    
    
    func numberOfSections(in tableView: UITableView) -> Int 
        return 2
    
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return [2,20] [section]
    
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        if indexPath.section == 0 
            let identifier = ["cell_month", "cell_week"][indexPath.row]
            let cell = tableView.dequeueReusableCell(withIdentifier: identifier)!
            return cell
         else 
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell")!
            
            return cell
        
    
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
        tableView.deselectRow(at: indexPath, animated: true)
        if indexPath.section == 0 
            let scope: FSCalendarScope = (indexPath.row == 0) ? .month : .week
            self.calendar.setScope(scope, animated: self.animationSwitch.isOn)
        
    
    
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat 
        return 10
    
    
    @IBAction func toggleClicked(sender: AnyObject) 
        if self.calendar.scope == .month 
            self.calendar.setScope(.week, animated: self.animationSwitch.isOn)
        else 
            self.calendar.setScope(.month, animated: self.animationSwitch.isOn)
        
        
    
    
    
    
    func calendar(_ calendar: FSCalendar, numberOfEventsFor date: Date) -> Int 

        let dateString = dateFormatter2.string(from: date)
                
        if self.datesWithEvent.contains(dateString)
            return 1
        
        
        if self.datesWithMultipleEvents.contains(dateString) 
            return 2
        
        
        return 0
    
    
    
    func calendar(_ calendar: FSCalendar, appearance: FSCalendarAppearance, eventDefaultColorsFor date: Date) -> [UIColor]? 
        
        let key = self.dateFormatter2.string(from: date)
        
        if self.datesWithMultipleEvents.contains(key)
            return [UIColor.blue]
        
        return nil
    
    

【问题讨论】:

您已经在委托calendar(_:didSelect:at monthPosition:) 中获得了选定的date。将date 从此处转发到一个新函数,该函数获取相应的事件数据并更新tableView 感谢您的回复!!我理解这个想法,但我需要帮助了解该代码的外观。我还是 Swift Development 的新手,无法弄清楚当我选择该单元格时应该如何更新 tableview。 【参考方案1】:

我是这样做的: 在我的“didSelect date”方法中,我重新格式化日期,然后调用 Firebase 的处理程序,在其中搜索特定日期。我对 Firebase 使用 wherefield 方法,该方法搜索与该日期匹配的所有事件。这些事件被列在一个数组中。然后我使用该数组列出想要的事件。

在我的视图控制器中

 func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) 
        let formatter = DateFormatter()
        formatter.dateFormat = "dd/MM-yyyy"
        let result = formatter.string(from: date)
        EventHandler.readEventAtDate(date: result, tableView: eventTable)
    

在我的处理程序中:

 static func readEventAtDate(date: String, tableView: UITableView) 
    //To feed tableview with specific date
    database.collection("Events").whereField("date", isEqualTo: date).getDocuments  (query, error) in
        if error != nil 
            print("Error: \(String(describing: error))")
         else 
            self.eventByDate.removeAll()
                for event in query!.documents 
                    let map = event.data()
                    let header = map["header"] as! String
                    let text = map["text"] as! String
                    let place = map["place"] as! String
                    let responsible = map["responsible"] as! String
                    let time = map["time"] as! String
                    let date = map["date"] as! String
                    let coordinates = map["coordinates"] as! GeoPoint
                    
                    let readEvent = Event(eventID: event.documentID, header: header, text: text, place: place, responsible: responsible, time: time, date: date, coordinates: coordinates)
                    eventByDate.append(readEvent)
                
            DispatchQueue.main.async 
                tableView.reloadData()
            
        
    

在我的表格视图中

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return EventHandler.eventByDate.count

【讨论】:

哇这太棒了!我会尝试将其插入我的日历中,看看我是否也可以让它为我工作。谢谢! 我正在考虑尝试实现这一点,但我认为这是 Firestore。我正在使用 Firebase 实时数据库。我正在查看文档。有没有办法用数据库而不是 Firestore 来实现这个功能?谢谢! 我以前没有使用过实时数据库。但是,如果您将它读入一个对象并像我一样传递它,它应该可以正常工作。您是否使用“完成”和“捕获”来加载数据库数据?如果是这样,您应该将对象加载到列表中,然后它应该与我的代码非常相似:) 太棒了!最后一个问题。在查看您的代码时,我了解除了您的 .eventByDate 之外的所有内容?正在使用吗? 哦,是的。那就是我在特定日期将所有事件读入的数组。所以我有两个数组:一个用于我拥有的每个事件(在日历上显示事件点)然后我有一个用于我单击的特定日期,它由 readEventAtDate 函数填充。

以上是关于Swift FSCalendar 在表格视图的日历显示事件中选择日期的主要内容,如果未能解决你的问题,请参考以下文章

如何在 FSCalendar swift 中禁用用户交互?

在 FSCalendar UIView 上放置按钮

如何删除 FSCalendar Swift 库中的天数

FSCalendar:从头开始查看标题?

FSCalendar - 从选定的日期创建 segue 到另一个视图控制器

如何在 tableviewcell 中显示选定的日期(在日历中)