简体   繁体   English

您必须使用 [EKEvent eventWithEventStore:] 来创建事件

[英]You must use [EKEvent eventWithEventStore:] to create an event

I have used CalenderKit on my app.我在我的应用程序上使用了 CalenderKit。 I have 2 types of users my goal is to collect calender data from targeted type and reflect it to other targeted type.我有两种类型的用户,我的目标是从目标类型收集日历数据并将其反映到其他目标类型。

  • First type went quite well, I have collected the date range data and simply pulled it to Firebase.第一个类型非常好,我收集了日期范围数据并将其拉到 Firebase。 Works fine.工作正常。

  • Second type makes me lose my mind.第二种让我失去理智。 So idea here is to pull stored data from Firebase, generate it to EKEvent and reflect it to an empty Calendar via CalenderKit.所以这里的想法是从 Firebase 中提取存储的数据,将其生成到 EKEvent 并通过 CalenderKit 将其反映到一个空的日历中。

// EventBox Class
struct EventBox {
    let startDate: String
    let endDate: String
    let isAllDay: Bool
    let title: String
}
    var userEventBox: [EventBox] = []
    
    func getEvents() {
        
        self.db.collection(XX).document(XX).collection("Calendar").addSnapshotListener { [self] (querySnapshot, error) in
            
            self.userEventBox = []
            
            if let e = error {
                print("There was an issue retrieving data from Firestore. \(e)")
            } else {
                
                if let snapshotDocuments = querySnapshot?.documents {
                    
                    for doc in snapshotDocuments {
                        
                        let data = doc.data()
                        if let title = data["title"] as? String ,
                           let startDate = data["startDate"] as? String ,
                           let endDate = data["endDate"] as? String ,
                           let isAllDay = data["isAllDay"] as? Bool
                        {
                            let newEventBox = EventBox(startDate: startDate, endDate: endDate, isAllDay: isAllDay, title: title)
                            self.userEventBox.append(newEventBox)
                            print(newEventBox)
                            self.generate() //Triggers second func after data collected and stored
                        }
                    }
                }
            }
        }
    }
    

    func generate() {
        
        for generation in userEventBox {

// I had issues when I tried to save data to Firebase as Date and pull it back. So I decided to store dates as String and use dateFormatter when downloaded.
            
            let isoStartDate = generation.startDate
            let isoEndDate = generation.endDate
            
            let dateFormatter = ISO8601DateFormatter()
            let startDate = dateFormatter.date(from:isoStartDate)!
            let endDate = dateFormatter.date(from:isoEndDate)!

      //dates formatted      

            if let event = EKEvent() as? EKEvent {

            event.title = generation.title
            event.isAllDay = generation.isAllDay
            event.startDate = startDate
            event.endDate = endDate
            event.calendar.cgColor = CGColor(red: 1, green: 1, blue: 1, alpha: 1)
                self.generated = [event]
            }
            
        }
    }
    
    var generated = [EKEvent()] // This variable is where I store all events after its generated

// And finally I am triggering the first getEvents func in override

    override func eventsForDate(_ date: Date) -> [EventDescriptor] {
        
        self.getEvents()
        
        let calenderKitEvents = generated.map(EKWrapper.init)
        
        return calenderKitEvents
    }
}

Problem is I am having this error and I couldnt figured it out for days.问题是我遇到了这个错误,我好几天都想不通。 Any help will be appreciated.任何帮助将不胜感激。

So here is what I did and what has been achieved with it.所以这就是我所做的以及用它取得的成就。

// created another class for generation
struct EventBoxWithDate {
    var startDate: Date
    var endDate: Date
    var isAllDay: Bool
    var title: String
    var color: CGColor
}

// Than I created a custom EKWrapper


final class CustomEKWrapper: EventDescriptor {
    public var dateInterval: DateInterval {
        get {
            DateInterval(start: ekEvent.startDate, end: ekEvent.endDate)
        }
        
        set {
            ekEvent.startDate = newValue.start
            ekEvent.endDate = newValue.end
        }
    }
    
    public var isAllDay: Bool {
        get {
            ekEvent.isAllDay
        }
        set {
            ekEvent.isAllDay = newValue
        }
    }
    
    public var text: String {
        get {
            ekEvent.title
        }
        
        set {
            ekEvent.title = newValue
        }
    }

    public var attributedText: NSAttributedString?
    public var lineBreakMode: NSLineBreakMode?
    
    public var color: UIColor {
        get {
            UIColor(cgColor: ekEvent.color)
        }
    }
    
    public var backgroundColor = UIColor()
    public var textColor = SystemColors.label
    public var font = UIFont.boldSystemFont(ofSize: 12)
    public weak var editedEvent: EventDescriptor? {
        didSet {
            updateColors()
        }
    }
    
    public private(set) var ekEvent: EventBoxWithDate
    
    public init(eventKitEvent: EventBoxWithDate) {
        self.ekEvent = eventKitEvent
        applyStandardColors()
    }
    
    public func makeEditable() -> Self {
        let cloned = Self(eventKitEvent: ekEvent)
        cloned.editedEvent = self
        return cloned
    }
    
    public func commitEditing() {
        guard let edited = editedEvent else {return}
        edited.dateInterval = dateInterval
    }
    
    private func updateColors() {
      (editedEvent != nil) ? applyEditingColors() : applyStandardColors()
    }
    
    /// Colors used when event is not in editing mode
    private func applyStandardColors() {
      backgroundColor = dynamicStandardBackgroundColor()
      textColor = dynamicStandardTextColor()
    }
    
    /// Colors used in editing mode
    private func applyEditingColors() {
      backgroundColor = color.withAlphaComponent(0.95)
      textColor = .white
    }
    
    /// Dynamic color that changes depending on the user interface style (dark / light)
    private func dynamicStandardBackgroundColor() -> UIColor {
      let light = backgroundColorForLightTheme(baseColor: color)
      let dark = backgroundColorForDarkTheme(baseColor: color)
      return dynamicColor(light: light, dark: dark)
    }
    
    /// Dynamic color that changes depending on the user interface style (dark / light)
    private func dynamicStandardTextColor() -> UIColor {
      let light = textColorForLightTheme(baseColor: color)
      return dynamicColor(light: light, dark: color)
    }
    
    private func textColorForLightTheme(baseColor: UIColor) -> UIColor {
      var h: CGFloat = 0, s: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0
      baseColor.getHue(&h, saturation: &s, brightness: &b, alpha: &a)
      return UIColor(hue: h, saturation: s, brightness: b * 0.4, alpha: a)
    }
    
    private func backgroundColorForLightTheme(baseColor: UIColor) -> UIColor {
      baseColor.withAlphaComponent(0.3)
    }
    
    private func backgroundColorForDarkTheme(baseColor: UIColor) -> UIColor {
      var h: CGFloat = 0, s: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0
      color.getHue(&h, saturation: &s, brightness: &b, alpha: &a)
      return UIColor(hue: h, saturation: s, brightness: b * 0.4, alpha: a * 0.8)
    }
    
    private func dynamicColor(light: UIColor, dark: UIColor) -> UIColor {
      if #available(iOS 13.0, *) {
        return UIColor { traitCollection in
          let interfaceStyle = traitCollection.userInterfaceStyle
          switch interfaceStyle {
          case .dark:
            return dark
          default:
            return light
          }
        }
      } else {
        return light
      }
    }
}

// And edited the code

    
    func getEvents() {
                
        self.db.collection(xx).document(xx).collection("Calendar").addSnapshotListener { [self] (querySnapshot, error) in
            
            self.userEventBox = []
            
            if let e = error {
                print("There was an issue retrieving data from Firestore. \(e)")
            } else {
                
                if let snapshotDocuments = querySnapshot?.documents {
                    
                    for doc in snapshotDocuments {
                        // @PAUL here I use timestamp for healthier usage as suggested.
                        let data = doc.data()
                        if let title = data["title"] as? String ,
                           let startDate = data["startDate"] as? Timestamp ,
                           let endDate = data["endDate"] as? Timestamp ,
                           let isAllDay = data["isAllDay"] as? Bool
                        {
                            let newEventBox = EventBox(startDate: startDate.dateValue(), endDate: endDate.dateValue(), isAllDay: isAllDay, title: title)
                            self.userEventBox.append(newEventBox)
                        }
                    }
                    self.generate()
                }
            }
        }
    }
    

    func generate() {
        

        for generation in userEventBox {
 
            let event = EventBoxWithDate(startDate: generation.startDate, endDate: generation.endDate, isAllDay: generation.isAllDay, title: generation.title, color: UIColor.green.cgColor)

           // EDITED THIS =>   self.generated = [event] 
           // TO THIS 
                self.generated.append(event)

            
        }
// AND ADDED
reloadData()
// EVERYTHING WORKS NOW
        }

    
    var generated: [EventBoxWithDate] = []
    
    override func eventsForDate(_ date: Date) -> [EventDescriptor] {
                
        let calenderKitEvents = generated.map(CustomEKWrapper.init)
        
        return calenderKitEvents
    }
}

//

This customization work quite well I can reflect my stored events on CalenderKit.这种定制效果很好,我可以在 CalenderKit 上反映我存储的事件。 Only thing left here is generated variable is storing all events but when code runs in override func and maps the generated variable it only shows the earliest event on the calender.这里只剩下生成的变量存储所有事件,但是当代码在覆盖函数中运行并映射生成的变量时,它只显示日历上最早的事件。 When I figure it out I will update you.当我弄清楚时,我会更新你。 Maybe it will help someone else.也许它会帮助别人。

UPDATED THE GENERATE FUNC AND IT WORKS NOW FOR ALL EVENTS更新了生成功能,它现在适用于所有事件

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM