AlbertMontserrat / AMGCalendarManager

EventKit helper for Swift 3
MIT License
30 stars 9 forks source link

Event in another store after editing? #1

Closed adamsmaka closed 7 years ago

adamsmaka commented 7 years ago

Hi, I love your calendar manager! I had no issues until I'm trying to introduce events editing in my app.

When I create an event, everything is ok. Then when I change its recurrenceRules, it lands in another store or something, because later manager can't remove all events throwing error:

"NSInvalidArgumentException", "Attempt to remove an object that does not belong to this store."

0 CoreFoundation 0x0000000104af5d4b __exceptionPreprocess + 171 1 libobjc.A.dylib 0x000000010455721e objc_exception_throw + 48 2 EventKit 0x00000001056a0c22 __30-[EKEventStore _deleteObject:]_block_invoke + 0 3 EventKit 0x0000000105656657 -[EKPersistentObject _removeObjectCore:fromValues:relation:] + 544 4 EventKit 0x000000010565693c -[EKPersistentObject primitiveRemoveRelatedObject:forKey:] + 180 5 EventKit 0x0000000105681698 -[EKPersistentCalendarItem removeDetachedItem:] + 265 6 EventKit 0x000000010568178f -[EKPersistentCalendarItem deleteSelfAndDetached] + 224 7 EventKit 0x0000000105668c2f -[EKEvent _deleteWithSpan:error:] + 786 8 EventKit 0x000000010566a3a2 -[EKEvent removeWithSpan:error:] + 509 9 EventKit 0x000000010568f3da -[EKEventStore removeEvent:span:commit:error:] + 299 10 AMGCalendarManager 0x0000000101d3e3e9 _TFC18AMGCalendarManager18AMGCalendarManagerP33_72EF97C106556493E498DAB06AB2172B11deleteEventfT5eventCSo7EKEvent6commitSb_Sb + 153 11 AMGCalendarManager 0x0000000101d3c16f _TFFFC18AMGCalendarManager18AMGCalendarManager15removeAllEventsFT10completionGSqFGSqCSo7NSError_T___T_U_FSbT_U_FTGSqS1__GSqGSaCSo7EKEvent___T_ + 463 12 AMGCalendarManager 0x0000000101d3c2e3 _TTRXFo_oGSqCSo7NSError_oGSqGSaCSo7EKEvent____XFo_iTGSqS__GSqGSaS0_____iT__ + 35 13 AMGCalendarManager 0x0000000101d3f301 _TPA__TTRXFo_oGSqCSo7NSError_oGSqGSaCSo7EKEvent____XFo_iTGSqS__GSqGSaS0_____iT__ + 81 14 AMGCalendarManager 0x0000000101d3c9a3 _TFFC18AMGCalendarManager18AMGCalendarManager12getAllEventsFT10completionGSqFTGSqCSo7NSError_GSqGSaCSo7EKEvent___T___T_U_FSbT_ + 1411 15 AMGCalendarManager 0x0000000101d39ca9 _TFC18AMGCalendarManager18AMGCalendarManager20requestAuthorizationfT10completionFSbT__T_ + 393 16 AMGCalendarManager 0x0000000101d3c3f6 _TFC18AMGCalendarManager18AMGCalendarManager12getAllEventsfT10completionGSqFTGSqCSo7NSError_GSqGSaCSo7EKEvent___T___T_ + 262 17 AMGCalendarManager 0x0000000101d3bf57 _TFFC18AMGCalendarManager18AMGCalendarManager15removeAllEventsFT10completionGSqFGSqCSo7NSError_T___T_U_FSbT_ + 423 18 AMGCalendarManager 0x0000000101d39ca9 _TFC18AMGCalendarManager18AMGCalendarManager20requestAuthorizationfT10completionFSbT__T_ + 393 19 AMGCalendarManager 0x0000000101d3bd66 _TFC18AMGCalendarManager18AMGCalendarManager15removeAllEventsfT10completionGSqFGSqCSo7NSError_T___T_ + 262

This is my code

func changeRepeatEndDate(_ eventId: String, endRepeat: Date, completion: (() -> ())?) {

    AMGCalendarManager.shared.getEvent(eventId: eventId) { (error, event) in
        if let event = event {

            if let recurrenceRules = event.recurrenceRules, recurrenceRules.count > 0 {
                for rule in recurrenceRules {
                    rule.recurrenceEnd = EKRecurrenceEnd(end: endRepeat)
                }
                self.calendarManager.saveEvent(event: event, completion: { (error) in
                    if let error = error {
                        fatalError("Error during saving an Event with ID \(eventId) - \(error.localizedDescription)")
                    } else {
                        completion?()
                    }
                })
            }

        } else {
            if let error = error {
                fatalError("Error during getting an Event with ID \(eventId) - \(error.localizedDescription)")
            } else {
                fatalError("No event in the store")
            }
        }
    }
}

AMGCalendarManager.shared.removeAllEvents()

adamsmaka commented 7 years ago

Ok, I found that if I call reset() just before removeAllEvents() then it all works properly. Anyway, weird behavior. :)

AlbertMontserrat commented 7 years ago

The error is because you are using two different calendar managers, i think. Try change: self.calendarManager.saveEvent for: AMGCalendarManager.shared.saveEvent

Tell me if this worked for you. Thanks!

adamsmaka commented 7 years ago

Thanks for answer Albert. I'm using the same one. It's just a shortcut variable what works well in every other case. private var calendarManager: AMGCalendarManager { return AMGCalendarManager.shared }

AlbertMontserrat commented 7 years ago

Check the new version I submitted. Hope that helps...

I added an option to save an event with span parameters, and now the EventStore is never recreated since the first time it's initialized

adamsmaka commented 7 years ago

Nothing changed, same error if I don't reset store manually before removeAll.

I noticed that changing that EKRecurrenceEnd adds additional string to the event.eventIdentifier

Before: 6D271F9B-C985-4867-AF01-AC8D0614CF72:460BA4B3-7C40-4FF1-8E08-6718DED3474E After: 6D271F9B-C985-4867-AF01-AC8D0614CF72:460BA4B3-7C40-4FF1-8E08-6718DED3474E/RID=512024940

it looks like updating recurrence end date make some troubles...

adamsmaka commented 7 years ago

Ok, the problem occurred only on Tests target, so don't worry. I can reset store there easily. In production code everything is fine. I just added a comment to your code, in one place you don't use an argument from function to pass it to eventStore.save method. Now when I set span to .futureEvents manually, eventIdentifier is no longer changing! ✅

AlbertMontserrat commented 7 years ago

Great, so my last vesion helped, right?