4

我想在我的 Mac 应用程序中包含一个按钮,按下该按钮将启动用户的默认日历应用程序。最好,我想让日历打开到某个日期。

这是针对 OS X Mountain Lion 的。

有没有通用的方法来做到这一点?

编辑:FWIW,这就是我现在正在做的事情:

- (IBAction)launchCalendarApp:(id)sender
{
    [[NSWorkspace sharedWorkspace] launchApplication:@"/Applications/Calendar.app"];
}

我知道像这样对路径进行硬编码是一个坏主意,这就是我问这个问题的原因。

更新:这就是我最终做的:

- (IBAction)launchCalendarApp:(id)sender
{
    NSWorkspace *sharedWorkspace = [NSWorkspace sharedWorkspace];
    NSString *iCalPath = [sharedWorkspace absolutePathForAppBundleWithIdentifier:@"com.apple.iCal"];
    BOOL didLaunch = [sharedWorkspace launchApplication:iCalPath];
    if (didLaunch == NO) {
        NSString *message = NSLocalizedString(@"The Calendar application could not be found.", @"Alert box message when we fail to launch the Calendar application");
        NSAlert *alert = [NSAlert alertWithMessageText:message defaultButton:nil alternateButton:nil otherButton:nil informativeTextWithFormat:@""];
        [alert setAlertStyle:NSCriticalAlertStyle];
        [alert runModal];
    }
}

听起来在开发出更好的 API 之前,所有可能的方法都是变通方法。我的解决方案类似于杰的建议。我使用捆绑标识符来获取路径,因为我认为它不那么脆弱。即使他们(或用户)决定重命名应用程序,Apple 也不太可能在未来更改捆绑 ID。不幸的是,这种方法不能让我到达一个特定的日期。当我有更多时间时,我将进一步研究其他一些建议(使用 ical:// 等)。

更新 2:NSGod 在下面有一个了不起的答案,如果您的应用程序没有被沙盒化,它还会将日历打开到特定日期。

4

4 回答 4

8

注意:当您更新您使用的内容时,我仍在研究这个,但我会添加这个 FWIW。

使用应用程序的包标识符通常是一种比单独使用名称更可靠的方式来引用应用程序,因为用户可以在 OS X 中移动或重命名应用程序,但他们不能轻易更改包标识符。此外,即使 Apple 将 iCal.app 重命名为 Calendar.app,CFBundleIdentifier它仍然是com.apple.iCal.

if (![[NSWorkspace sharedWorkspace]
                launchAppWithBundleIdentifier:@"com.apple.iCal"
                                      options:NSWorkspaceLaunchDefault
               additionalEventParamDescriptor:nil
                             launchIdentifier:NULL]) {
    NSLog(@"launching Calendar.app failed!");
}

即使您的应用程序被沙盒化,上面的代码也可以工作。您可能会尝试创建一个自定义NSAppleEventDescriptor来指定类似于以下 AppleScript 代码的内容,但它可能会因为沙箱而被拒绝:

view calendar at date "Sunday, April 8, 2012 4:28:43 PM"

如果您的应用程序不必被沙盒化,那么使用 Scripting Bridge 会容易得多,并且使用该方法可以选择特定的NSDate.

使用 ScriptingBridge 的示例项目:OpenCalendar.zip

在该项目中,我使用以下代码:

SBCalendarApplication *calendarApp = [SBApplication
              applicationWithBundleIdentifier:@"com.apple.iCal"];
[calendarApp viewCalendarAt:[self.datePicker dateValue]];

这将启动 Calendar.app/iCal.app 并将日历更改为指定日期。

于 2013-04-08T21:42:10.053 回答
4

所以现在听起来你要么不得不诉诸硬连线的方法,例如

// Launches Calendar.app on 10.7+
[[NSWorkspace sharedWorkspace] launchApplication:@"Calendar"];

或者使用 OS X 上的 Calendar/iCal 支持的 URL 方案(NSGod 在下面的评论中指出)类似于URL 方案在日期或事件打开 iCal 应用程序?

// Launches iCal (works at least with 10.6+)
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"ical://"]];
于 2013-04-08T17:16:09.190 回答
1

您可以尝试使用 EventKit 创建所需日期和时间的 EKCalendarItem 实例,打开该事件,然后立即将其删除。如果时机合适,它甚至可能不会在用户日历上明显闪烁/关闭。

这是另一个 kludge,但在 NSWorkspace 有一个 -openDate: 方法之前,kludges 是唯一的资源。

于 2013-04-08T17:47:23.707 回答
0

正如在这个线程上所讨论的,似乎没有启动 iCal 的 url 方案

在某个日期或事件打开 iCal 应用程序的 URL 方案?

于 2013-04-08T16:19:57.537 回答