ios - 从 WatchExtension 在日历中添加事件

标签 ios iphone swift calendar watchkit

我询问有关从 Watch Extension 添加新事件到日历的问题。 我正在创建一个绑定(bind)到 IOS 应用程序的 Apple Watch 应用程序, watch 应用程序读取通过 TableView 中的应用程序上下文传递给它的 JSON 字符串。 我需要做的是当用户点击表格单元格时,新事件应该从 watch 添加到 iPhone 日历中。

我可以使用以下代码从应用程序成功地将事件添加到日历

func WatchEvent(){


let eventStore = EKEventStore()

let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
let date = dateFormatter.dateFromString("2016-05-28T20:20:00")

let endDate = date!.dateByAddingTimeInterval(1 * 60 * 60) // One hour

if (EKEventStore.authorizationStatusForEntityType(.Event) != EKAuthorizationStatus.Authorized) {
eventStore.requestAccessToEntityType(.Event, completion: {
granted, error in
self.createEvent(eventStore, title: "TestTitile :"+"Dr.Test", startDate: date!, endDate: endDate , alertinterval:-(24 * 60 * 60) , notes: "TestNote" , appointmentlocation: "TestLocation")
})


} else {
  self.createEvent(eventStore, title: "TestTitlte :"+"Dr.Test", startDate: date!, endDate: endDate , alertinterval:-(24 * 60 * 60) , notes: "TestNote" , appointmentlocation: "TestLocation")

}

//==================================================================

func createEvent(eventStore: EKEventStore, title: String, startDate: NSDate, endDate: NSDate, alertinterval:NSTimeInterval , notes: String , appointmentlocation: String) {
    let event = EKEvent(eventStore: eventStore)


    event.title = title
    event.startDate = startDate
    event.endDate = endDate
    event.calendar = eventStore.defaultCalendarForNewEvents
    var interval = NSTimeInterval()
    interval = alertinterval
    //-(24 * 60 * 60) // -(30 * 60) // -(24 * 60 * 60)
    let alarm  =  EKAlarm(relativeOffset: interval)
    event.addAlarm(alarm)
    event.notes = notes
    event.location = appointmentlocation


    do {
        try eventStore.saveEvent(event, span: .ThisEvent)
        // savedEventId = event.eventIdentifier
    } catch {
        print("Error Happened")
    }
}

但我仍然坚持从 Watch 扩展添加它,因为 SaveEvent 方法在 WatchOS 中不可用。 那么我该怎么做才能在 Apple Watch 上执行此操作?

最佳答案

我认为现在回答这个问题为时已晚,但如果它对像我这样的人有帮助,那将是我的荣幸:) 在 watchOS2 中,您无法直接从 watchOS 保存事件,也无法从配对设备访问钥匙串(keychain)详细信息。因此,为此,您需要通过 watch 连接框架向配对设备发送请求,并尝试将事件保存在配对设备(iPhone)中。 在做任何事情之前,首先在 iOS 和 watchOS 类中设置 watch 连接,例如应用程序委托(delegate)的 didFinishLaunching 和 watchOS 任何 View Controller 初始化方法(从您要添加事件的地方)。

#import <WatchConnectivity/WatchConnectivity.h>

if ([WCSession isSupported]) {
        WCSession *session = [WCSession defaultSession];
        session.delegate = self;
        [session activateSession];
    }

之后继续下一步,即 watchOS 方法保存事件:-

    -(void)addEventToDeviceCalendar
    {
        self.eventStore = [[EKEventStore alloc] init];
[self.eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
            if (!granted) { return; }
            NSMutableDictionary *eventInfoDict = [NSMutableDictionary new];
            self.defaultCalendar = [self.eventStore defaultCalendarForNewEvents];

            EKEvent *event = [EKEvent eventWithEventStore:self.eventStore];
            event.title = title;
            [eventInfoDict setObject:title forKey:@"eventTitle"];

            if (eventDate)
            {
                NSString *dateString = eventDate;
                //dateString = [NSString stringWithFormat:@"%@ %@",eventDate,@"09:00:00"];
                if (eventTime) {
                    dateString = [NSString stringWithFormat:@"%@ %@",eventDate,eventTime];
                    [eventInfoDict setObject:@YES forKey:@"eventTime"];
                }
                [eventInfoDict setObject:dateString forKey:@"eventDate"];
                NSDate *date = [[MyDataObject sharedInstance] dateFromDateString:dateString];
                event.startDate = date;
            }
            else{
                event.startDate = [NSDate date]; //today
            }


            event.endDate = [event.startDate dateByAddingTimeInterval:60*60];  //set 1 hour meeting
            event.location = venue;
            [eventInfoDict setObject:venue forKey:@"location"];
            event.notes = description;
            [eventInfoDict setObject:description forKey:@"notes"];
            [event setCalendar:self.defaultCalendar];

            NSMutableDictionary *trackDict = [[NSMutableDictionary alloc] init];
            [trackDict setObject:kAppleWatchAddEvent forKey:kRequestTypeWatchKit];
            [trackDict setValue:eventInfoDict forKey:kAppleWatchEvent];

            // Only if using WatchOS 2 or higher
    [[WCSession defaultSession] sendMessage: trackDict
                               replyHandler:^(NSDictionary *replyHandler) {
                                   NSString *obj = [replyHandler valueForKey:@"reply"];
                                   NSLog(@"%@",obj);
                                   if ([obj isEqual:kAppleWatchAddEvent])
                                   {
                                      savedEventId = event.eventIdentifier;
                                   }



                               }
                               errorHandler:^(NSError *error) {

                               }
     ];
            //[self.eventStore saveEvent:event span:EKSpanThisEvent commit:YES error:&err]; ******* Watch OS does not support save or remove event ******

        }];
    }

之后你需要像这样处理 iOS 端的回复回调函数:-

- (void)session:(nonnull WCSession *)session didReceiveMessage:(NSDictionary<NSString *,id> *)message replyHandler:(void(^)(NSDictionary<NSString *,id> *))replyHandler {

    NSString *requestType = message[kRequestTypeWatchKit];

    if ([requestType isEqual:kAppleWatchAddEvent]) {

        NSMutableDictionary *event = message[kAppleWatchEvent];
        [self addWatchEventToDeviceCalendar:event replyHandler:^(NSDictionary *replyHandlerForWatch) {
             replyHandler(replyHandlerForWatch);
         }];
    }
}

-(void)addWatchEventToDeviceCalendar:(NSMutableDictionary *)eventObj replyHandler:(void(^)(NSDictionary<NSString *,id> *))replyHandler
{
    [self.eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
        if (!granted) { replyHandler(@{@"reply":@"notAdded"}); }

        self.defaultCalendar = [self.eventStore defaultCalendarForNewEvents];

        EKEvent *event = [EKEvent eventWithEventStore:self.eventStore];
        event.title = [eventObj objectForKey:@"eventTitle"];

        NSDateFormatter *df = [[NSDateFormatter alloc] init];
        [df setLocale:[NSLocale localeWithLocaleIdentifier:[APP_DELEGATE LanguageCode]]];

        if (eventObj[@"eventTime"]) {
            [df setDateFormat:@"EEE MMM d h:mma"];
        }else{
            [df setDateFormat:@"EEE MMM d"];
        }

        if (eventObj[@"eventDate"])
        {

            NSString *dateString =  [eventObj objectForKey:@"eventDate"];
            NSDate *date = [df dateFromString:dateString];
            event.startDate = date;
        }
        else{
            event.startDate = [NSDate date]; //today
        }


        event.endDate = [event.startDate dateByAddingTimeInterval:60*60];  //set 1 hour meeting
        event.location = [eventObj objectForKey:@"location"];

        event.notes = [eventObj objectForKey:@"notes"];

        [event setCalendar:self.defaultCalendar];

        NSError *err = nil;
        [self.eventStore saveEvent:event span:EKSpanThisEvent commit:YES error:&err];
        replyHandler(@{@"reply":kAppleWatchAddEvent});

    }];
}

现在非常重要,请不要忘记使用 WatchKit 框架的这些方法来检查和保留 iOS 和 watchOS 端的连接状态

#pragma mark - Standard WatchKit Delegate

- (void)sessionDidDeactivate:(WCSession *)session
{
    if(WCSession.isSupported){
        WCSession* session = WCSession.defaultSession;
        session.delegate = self;
        [session activateSession];

    }
}
-(void)sessionWatchStateDidChange:(nonnull WCSession *)session
{
    if(WCSession.isSupported){
        WCSession* session = WCSession.defaultSession;
        session.delegate = self;
        [session activateSession];

        if(session.reachable){
            NSLog(@"session.reachable");
        }

        if(session.paired){
            if(session.isWatchAppInstalled){

                if(session.watchDirectoryURL != nil){

                }
            }
        }
    }
}
#pragma mark - WatchKit Handlers

- (void)session:(WCSession *)session activationDidCompleteWithState:(WCSessionActivationState)activationState
          error:(NSError *)error
{
    NSLog(@"PHONE - activationDidCompleteWithState");
}

关于ios - 从 WatchExtension 在日历中添加事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36789539/

相关文章:

ios - 在iOS中合并两个PNG UIImage,而不会失去透明度

ios - iOS 内存泄漏

swift - 为类创建通用委托(delegate)

ios - UILabel 手势响应

arrays - Swift - 需要对星期几的字符串数组进行排序

iphone - Apple iOS6 map - 目的地地址 > 显示公司名称而不是纬度/经度

iOS-Swift UIApplication.shared.isIdleTimerDisabled = true 在 AppStore 审核后不起作用

iphone - 连接:willCacheResponse will never get called

iphone - 如何在 Core Data 中分配相关对象?

iphone - 解决CoreData错误: NULL _cd_rawData but the object is not being turned into a fault