Быстрый. Событие не сохраняется в календаре

Я пытаюсь скопировать определенные события из всех календарей в целевой календарь. К сожалению, мои события не сохраняются в целевом календаре.

Просто мой код по шагам:

  • Проверить разрешения (успешно)
  • Загрузить календари (успешно)
  • Загрузить события (успешно)
  • Сохранить события (не удалось)

Я уверен, что есть события, которые нужно сохранить с терминала, который пару раз печатает «Попытка сохранения».

И похоже, что код проходит через «try self.eventStore.save(event, span: .thisEvent)» и выходит из функции без вызова «Saved» или ввода предложения catch.

Есть исходный код:

import UIKit
import EventKit

class ViewController: UIViewController{

    @IBOutlet weak var status: UILabel!

    var calendars: [EKCalendar]?

    var targetCalendar: EKCalendar?
    var targetCalendarEvents: [EKEvent]?

    let eventStore = EKEventStore()

    let targetCalendarName = "TargetCalendarName"

    override func viewDidLoad() {
        super.viewDidLoad()
    }

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

    override func viewWillAppear(_ animated: Bool) {
        DispatchQueue.main.async{
            self.status.text = "Idle"
        }

        checkCalendarAuthorizationStatus()
    }

    func checkCalendarAuthorizationStatus() {
        let status = EKEventStore.authorizationStatus(for: EKEntityType.event)

        switch (status) {
        case EKAuthorizationStatus.notDetermined:
            // This happens on first-run
            requestAccessToCalendar()
        case EKAuthorizationStatus.authorized:
            // Things are in line with being able to show the calendars in the table view
            loadCalendars()
            loadEvents()
        case EKAuthorizationStatus.restricted, EKAuthorizationStatus.denied:
            // We need to help them give us permission
            print("Missing permissions [00]")
        }
    }

    func requestAccessToCalendar() {
        eventStore.requestAccess(to: EKEntityType.event, completion: {
            (accessGranted: Bool, error: Error?) in

            if accessGranted == true {
                DispatchQueue.main.async(execute: {
                    self.loadCalendars()
                    self.loadEvents()
                })
            } else {
                print("Missing permissions [01]")
            }
        })
    }

    func loadEvents(){
        print("Loading..")
        DispatchQueue.main.async{
            self.status.text = "Loading"
        }

        let eventStore = EKEventStore()

        var initialized = false

        //Two months
        let dateTo = NSDate(timeIntervalSinceNow: +30*24*3600 * 2)

        for calendar in self.calendars! {
            let predicate = eventStore.predicateForEvents(withStart: Date() as Date as Date, end: dateTo as Date, calendars: [calendar])

            let events = eventStore.events(matching: predicate)

            if calendar.title == targetCalendarName  {
                print("Initialized")
                targetCalendar = calendar
                targetCalendarEvents = events
                initialized = true
            }
        }

        if(!initialized){
            print("Not Initialized")
        } else {
            for calendar in self.calendars! {

                let predicate = eventStore.predicateForEvents(withStart: Date() as Date as Date, end: dateTo as Date, calendars: [calendar])

                let events = eventStore.events(matching: predicate)

                if calendar.title != targetCalendarName && calendar.title != "Contacts" {

                    //print("Loaded Calendar \(calendar.title)")
                    print("Loaded Calendar")

                    for event in events {
                        if(!(event.location?.isEmpty)!){
                            //print("Event \(event.location ?? "Missing Location") \(event.startDate) \(event.endDate)")

                            addEventToTarget(eventToAdd: event)
                        }
                    }
                }
            }
        }


        DispatchQueue.main.async {
            self.status.text = "Done"
        }
        print("Done")
    }

    func loadCalendars() {
        self.calendars = eventStore.calendars(for: EKEntityType.event)
    }

    func addEventToTarget(eventToAdd: EKEvent){

        eventStore.requestAccess(to: .event) { (granted, error) in

            for event in self.targetCalendarEvents! {
                if(!(event.location?.isEmpty)!){
                    if(
                        eventToAdd.title == event.title &&
                        eventToAdd.startDate == event.startDate &&
                        eventToAdd.endDate == event.endDate
                    ){
                        print("Possible duplicate - skipping")
                        return
                    }
                }
            }

            if (granted) && (error == nil) {

                let event:EKEvent = EKEvent(eventStore: self.eventStore)

                event.title = eventToAdd.title
                event.startDate = eventToAdd.startDate
                event.endDate = eventToAdd.endDate
                event.notes = ""
                event.location = eventToAdd.location

                event.calendar = self.targetCalendar

                //print("Trying to save \(event.title) \(String(describing: event.location))")
                print("Trying to save")
                do {
                    try self.eventStore.save(event, span: .thisEvent)
                    print("Saved \(event.title) \(String(describing: event.location)) in \(event.calendar.title)")
                } catch {
                    print("failed to save event with error : \(error as NSError)")
                }
            }
            else{

                print("failed to save event with error : \(String(describing: error)) or access not granted")
            }
        }
    }
}

TargetCalendarName – правильное название календаря


Иногда есть события, которые сохраняются успешно, но только пара из них (2-5) из сотен, которые должны сохраняться. Я понятия не имею, почему. Так что 5 на 200 мне мало.


person Shaq    schedule 10.06.2018    source источник
comment
Вы бросаете много вызовов eventStore.requestAccess(to: .event) { и сохраняете в обработчике завершения. Каждый из этих вызовов обработчика завершения может возвращаться в другом потоке, поэтому у вас возникает беспорядок с потоками. Почему вы это делаете? Проверьте доступ один раз заранее, а затем просмотрите все, что вы хотите сохранить, и сохраните их.   -  person matt    schedule 11.06.2018
comment
@matt хорошее замечание, попробую   -  person Shaq    schedule 11.06.2018
comment
Общий комментарий: не используйте NSDate, просто используйте Date, а Date() as Date as Date можно упростить до Date(). Это нормально для быстрого теста, но вы не должны рассчитывать диапазоны времени, умножая секунды; начало/конец летнего времени нарушит это   -  person Paulw11    schedule 11.06.2018


Ответы (1)


Спасибо @matt за предложение решения.

Теперь я сохраняю события ОДИН РАЗ (ранее я запрашивал доступ для каждого события, что очень плохо), поэтому я запрашиваю доступ к eventStore один раз и могу успешно сохранять события.

func saveEvents(){
    eventStore.requestAccess(to: .event) { (granted, error) in

        if (granted) && (error == nil) {

            for event in self.eventsToCopy {
                print("Trying to save")
                do {
                    try self.eventStore.save(event, span: .thisEvent)
                    print("Saved \(event.title) \(String(describing: event.location)) in \(event.calendar.title)")
                } catch {
                    print("failed to save event with error : \(error as NSError)")
                }
            }
        }
        else{

            print("failed to save event with error : \(String(describing: error)) or access not granted")
        }
    }
}
person Shaq    schedule 11.06.2018