Programowo dodaj zdarzenie niestandardowe do kalendarza iPhone'a

183

Czy istnieje sposób, aby dodać wydarzenie iCal do kalendarza iPhone'a z poziomu niestandardowej aplikacji?

Vadim
źródło

Odpowiedzi:

167

Na podstawie dokumentacji Apple zmieniło się to nieco od wersji iOS 6.0.

1) Należy zażądać dostępu do kalendarza użytkownika poprzez „requestAccessToEntityType: Complete:” i wykonać obsługę zdarzenia wewnątrz bloku.

2) Musisz zatwierdzić wydarzenie teraz lub przekazać parametr „commit” do swojego wywołania save / remove

Wszystko inne pozostaje takie samo ...

Dodaj platformę EventKit i #import <EventKit/EventKit.h>do swojego kodu.

W moim przykładzie mam właściwość instancji NSString * saveEventId.

Aby dodać wydarzenie:

    EKEventStore *store = [EKEventStore new];
    [store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
        if (!granted) { return; }
        EKEvent *event = [EKEvent eventWithEventStore:store];
        event.title = @"Event Title";
        event.startDate = [NSDate date]; //today
        event.endDate = [event.startDate dateByAddingTimeInterval:60*60];  //set 1 hour meeting
        event.calendar = [store defaultCalendarForNewEvents];
        NSError *err = nil;
        [store saveEvent:event span:EKSpanThisEvent commit:YES error:&err];
        self.savedEventId = event.eventIdentifier;  //save the event id if you want to access this later
    }];

Usuń wydarzenie:

    EKEventStore* store = [EKEventStore new];
    [store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
        if (!granted) { return; }
        EKEvent* eventToRemove = [store eventWithIdentifier:self.savedEventId];
        if (eventToRemove) {
            NSError* error = nil;
            [store removeEvent:eventToRemove span:EKSpanThisEvent commit:YES error:&error];
        }
    }];

Spowoduje to dodanie wydarzeń do domyślnego kalendarza, jeśli masz wiele kalendarzy, dowiesz się, który to jest

Szybka wersja

Musisz zaimportować strukturę EventKit

import EventKit

Dodaj wydarzenie

let store = EKEventStore()
store.requestAccessToEntityType(.Event) {(granted, error) in
    if !granted { return }
    var event = EKEvent(eventStore: store)
    event.title = "Event Title"
    event.startDate = NSDate() //today
    event.endDate = event.startDate.dateByAddingTimeInterval(60*60) //1 hour long meeting
    event.calendar = store.defaultCalendarForNewEvents
    do {
        try store.saveEvent(event, span: .ThisEvent, commit: true)
        self.savedEventId = event.eventIdentifier //save event id to access this particular event later
    } catch {
        // Display error to user
    }
}

Usuń wydarzenie

let store = EKEventStore()
store.requestAccessToEntityType(EKEntityTypeEvent) {(granted, error) in
    if !granted { return }
    let eventToRemove = store.eventWithIdentifier(self.savedEventId)
    if eventToRemove != nil {
        do {
            try store.removeEvent(eventToRemove, span: .ThisEvent, commit: true)
        } catch {
            // Display error to user
        }
    }
}
William T.
źródło
6
u mnie nie działa, wszystko idzie bez błędów ale nie ma wydarzenia w kalendarzu
Boris Gafurov
Wszystko jest przechowywane w obiekcie ekevent, ale nie jest przechowywane w kalendarzu. Hlp me
1
@William T: Czy mogę zaprezentować ekran dodawania wydarzenia w aplikacji Kalendarza (używając schematu URL) i przekazać informacje o wydarzeniu, aby po pojawieniu się ekranu dodawania wydarzenia zawierały wstępnie wypełnione dane. Użytkownik musi tylko nacisnąć przycisk dodawania zdarzenia. W Twoim przykładzie zdarzenie dodane bez wskazania dla użytkownika.
Ans
1
jeśli wszystko wydaje się działać, ale nie pojawia się żaden kalendarz, sprawdź, czy problem dotyczy kalendarzy Cloud VS Local. Jeśli masz połączenie kalendarzy w chmurze i kalendarzy lokalnych, kalendarze w chmurze mogą wymusić ukrycie kalendarzy lokalnych.
zonabi
2
@ReddyBasha Kiedy dodajesz wydarzenie, musisz zapisać eventIdentifier i zachować go do wykorzystania w przyszłości. Powinieneś użyć tego identyfikatora zdarzenia, gdy chcesz je usunąć.
William T.
153

Możesz to zrobić za pomocą środowiska Event Kit w systemie OS 4.0.

Kliknij prawym przyciskiem myszy grupę FrameWorks w nawigatorze grup i plików po lewej stronie okna. Wybierz „Dodaj”, a następnie „Istniejące FrameWorks”, a następnie „EventKit.Framework”.

Wtedy powinieneś móc dodawać wydarzenia z takim kodem:

#import "EventTestViewController.h"
#import <EventKit/EventKit.h>

@implementation EventTestViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    EKEventStore *eventStore = [[EKEventStore alloc] init];

    EKEvent *event  = [EKEvent eventWithEventStore:eventStore];
    event.title     = @"EVENT TITLE";

    event.startDate = [[NSDate alloc] init];
    event.endDate   = [[NSDate alloc] initWithTimeInterval:600 sinceDate:event.startDate];

    [event setCalendar:[eventStore defaultCalendarForNewEvents]];
    NSError *err;
    [eventStore saveEvent:event span:EKSpanThisEvent error:&err];       
}

@end
WoodenKitty
źródło
18
Dzięki za opublikowanie tego. Przypomnienie dla wszystkich, którzy to czytają: uważaj na wycieki pamięci. W tym przykładzie kodu jest kilka. Ponadto najlepsze praktyki nakazują sprawdzanie wartości „err” po saveEvent: span: error i odpowiednie postępowanie.
David Carney,
Czy wiesz, jak dodać zdarzenie cykliczne? jak impreza na każdy poniedziałek?
Jay Vachhani
5
Dodaj programowo zdarzenie powtarzania: sprawdź to developer.apple.com/library/ios/#documentation/EventKit/… . Inną opcją jest użycie domyślnych kontrolerów widoku dostarczonych przez platformę do dodawania / edytowania wydarzeń (takich jak aplikacja Calendar At-A-Glance bit.ly/cJq4Bh ). Informacje na temat tej opcji można znaleźć na stronie developer.apple.com/library/ios/#documentation/EventKitUI/…
DenTheMan
Aby dodać frameworki w XCode 4, zobacz to pytanie SO: stackoverflow.com/questions/3352664/ ...
Nate
1
4.0? nie polecę za 6 lat patrz powyższa odpowiedź
Boris Gafurov
13

Tak, nadal nie ma do tego API (2.1). Ale wydawało się, że w WWDC wiele osób było już zainteresowanych funkcjonalnością (w tym ja) i zalecono, aby przejść do poniższej witryny i utworzyć prośbę o funkcję w tym celu. Jeśli zainteresowanie jest wystarczające, mogą w końcu przenieść ICal.framework do publicznego SDK.

https://developer.apple.com/bugreporter/

keremk
źródło
5
odpowiedź jest nieaktualna, rozważ jej usunięcie
Jasper
12

Dostęp do kalendarza jest dodawany w iPhone OS 4.0 :


Aplikacje Calendar Access mogą teraz tworzyć i edytować wydarzenia bezpośrednio w aplikacji Kalendarz za pomocą narzędzia Event Kit.
Twórz wydarzenia cykliczne, ustawiaj godziny rozpoczęcia i zakończenia oraz przypisuj je do dowolnego kalendarza na urządzeniu.

Chris S.
źródło
1
Twój link jest teraz uszkodzony.
Adil Soomro
6

Wdrożenie Swift 4.0:

użyj importu na górze strony według import EventKit

następnie

@IBAction func addtoCalendarClicked(sender: AnyObject) {

    let eventStore = EKEventStore()

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

        if (granted) && (error == nil) {
            print("granted \(granted)")
            print("error \(error)")

            let event = EKEvent(eventStore: eventStore)

            event.title = "Event Title"
            event.startDate = Date()
            event.endDate = Date()
            event.notes = "Event Details Here"
            event.calendar = eventStore.defaultCalendarForNewEvents

            var event_id = ""
            do {
                try eventStore.save(event, span: .thisEvent)
                event_id = event.eventIdentifier
            }
            catch let error as NSError {
                print("json error: \(error.localizedDescription)")
            }

            if(event_id != ""){
                print("event added !")
            }
        }
    })
}
Dashrath
źródło
czy możesz mi pomóc z kalendarzem Google dotyczącym tej samej odpowiedzi @Dashrath
Dilip Tiwari
5

Możesz dodać wydarzenie za pomocą interfejsu Event API, takiego jak opisany przez Tristana, a także możesz dodać wydarzenie z Kalendarza Google, które pojawi się w kalendarzu iOS.

za pomocą klienta API Objective-C firmy Google

  - (void)addAnEvent {
  // Make a new event, and show it to the user to edit
  GTLCalendarEvent *newEvent = [GTLCalendarEvent object];
  newEvent.summary = @"Sample Added Event";
  newEvent.descriptionProperty = @"Description of sample added event";

  // We'll set the start time to now, and the end time to an hour from now,
  // with a reminder 10 minutes before
  NSDate *anHourFromNow = [NSDate dateWithTimeIntervalSinceNow:60*60];
  GTLDateTime *startDateTime = [GTLDateTime dateTimeWithDate:[NSDate date]
                                                    timeZone:[NSTimeZone systemTimeZone]];
  GTLDateTime *endDateTime = [GTLDateTime dateTimeWithDate:anHourFromNow
                                                  timeZone:[NSTimeZone systemTimeZone]];

  newEvent.start = [GTLCalendarEventDateTime object];
  newEvent.start.dateTime = startDateTime;

  newEvent.end = [GTLCalendarEventDateTime object];
  newEvent.end.dateTime = endDateTime;

  GTLCalendarEventReminder *reminder = [GTLCalendarEventReminder object];
  reminder.minutes = [NSNumber numberWithInteger:10];
  reminder.method = @"email";

  newEvent.reminders = [GTLCalendarEventReminders object];
  newEvent.reminders.overrides = [NSArray arrayWithObject:reminder];
  newEvent.reminders.useDefault = [NSNumber numberWithBool:NO];

  // Display the event edit dialog
  EditEventWindowController *controller = [[[EditEventWindowController alloc] init] autorelease];
  [controller runModalForWindow:[self window]
                          event:newEvent
              completionHandler:^(NSInteger returnCode, GTLCalendarEvent *event) {
                // Callback
                if (returnCode == NSOKButton) {
                  [self addEvent:event];
                }
              }];
}
Iggy
źródło
4

Aktualizacja dla Swift 4 dla odpowiedzi Dashrath

import UIKit
import EventKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let eventStore = EKEventStore()

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

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


                let event = EKEvent(eventStore: eventStore)

                event.title = "My Event"
                event.startDate = Date(timeIntervalSinceNow: TimeInterval())
                event.endDate = Date(timeIntervalSinceNow: TimeInterval())
                event.notes = "Yeah!!!"
                event.calendar = eventStore.defaultCalendarForNewEvents

                var event_id = ""
                do{
                    try eventStore.save(event, span: .thisEvent)
                    event_id = event.eventIdentifier
                }
                catch let error as NSError {
                    print("json error: \(error.localizedDescription)")
                }

                if(event_id != ""){
                    print("event added !")
                }
            }
        })
    }

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


}

nie zapomnij również dodać pozwolenia na używanie kalendarza obraz do użytku prywatnego

luhuiya
źródło
2

Kod roboczy w Swift-4.2

import UIKit
import EventKit
import EventKitUI

class yourViewController: UIViewController{

    let eventStore = EKEventStore()

    func addEventToCalendar() {

    eventStore.requestAccess( to: EKEntityType.event, completion:{(granted, error) in
        DispatchQueue.main.async {
            if (granted) && (error == nil) {
                let event = EKEvent(eventStore: self.eventStore)
                event.title = self.headerDescription
                event.startDate = self.parse(self.requestDetails.value(forKey: "session_time") as? String ?? "")
                event.endDate = self.parse(self.requestDetails.value(forKey: "session_end_time") as? String ?? "")
                let eventController = EKEventEditViewController()
                eventController.event = event
                eventController.eventStore = self.eventStore
                eventController.editViewDelegate = self
                self.present(eventController, animated: true, completion: nil)

            }
        }


       })
    }

}

Teraz otrzymamy ekran wydarzenia i tutaj możesz również zmodyfikować swoje ustawienia:

wprowadź opis obrazu tutaj

Teraz dodaj metodę delegata do obsługi Cancel i dodaj akcję przycisku zdarzenia na ekranie zdarzenia:

    extension viewController: EKEventEditViewDelegate {

    func eventEditViewController(_ controller: EKEventEditViewController, didCompleteWith action: EKEventEditViewAction) {
        controller.dismiss(animated: true, completion: nil)

    }
}

Uwaga: nie zapomnij dodać klucza NSCalendarsUsageDescription do pliku info plist.

Alok
źródło
1

Pamiętaj, aby ustawić endDate w utworzonym zdarzeniu, jest to obowiązkowe.

W przeciwnym razie zakończy się niepowodzeniem (prawie bezgłośnie) z tym błędem:

"Error Domain=EKErrorDomain Code=3 "No end date has been set." UserInfo={NSLocalizedDescription=No end date has been set.}"

Kompletny działający kod dla mnie to:

EKEventStore *store = [EKEventStore new];
[store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
    if (!granted) { return; }
    EKEvent *calendarEvent = [EKEvent eventWithEventStore:store];
    calendarEvent.title = [NSString stringWithFormat:@"CEmprendedor: %@", _event.name];
    calendarEvent.startDate = _event.date;
    // 5 hours of duration, we must add the duration of the event to the API
    NSDate *endDate = [_event.date dateByAddingTimeInterval:60*60*5];
    calendarEvent.endDate = endDate;
    calendarEvent.calendar = [store defaultCalendarForNewEvents];
    NSError *err = nil;
    [store saveEvent:calendarEvent span:EKSpanThisEvent commit:YES error:&err];
    self.savedEventId = calendarEvent.eventIdentifier;  //saving the calendar event id to possibly deleted them
}];
halbano
źródło
1
Pamiętaj też, że data zakończenia musi być równa lub większa niż data rozpoczęcia. W przeciwnym razie pojawi się kolejny błąd.
nastrojowy
0

Pomysł na Google jest fajny, ale ma problemy.

Mogę z powodzeniem otworzyć ekran wydarzeń kalendarza Google - ale tylko w głównej wersji komputerowej i nie wyświetla się poprawnie na iPhonie Safari. Mobilny kalendarz Google, który wyświetla się poprawnie w Safari, nie działa z interfejsem API do dodawania wydarzeń.

W tej chwili nie widzę dobrego wyjścia z tego.

xgretsch
źródło
0

Proste .... użyj biblioteki tapku .... możesz wygooglować to słowo i użyć go ... jego otwarte źródło ... ciesz się ..... nie ma potrzeby bugowania tymi kodami ....

Rajesh_Bangalore
źródło
Czy kalendarz Tapku Library może synchronizować się z wydarzeniami w aplikacji kalendarza
coder1010
Wiem tylko, że biblioteka Tapku jest kontrolką komponentu kalendarza, która ma opcję o nazwie Źródło danych. A więc zapisywanie skąd źródła, z którego pobierasz, jest najbardziej
aktualne