9

我需要在系统启动时启动我的应用程序,但问题是:它已经在 App Store 中,所以我必须遵循一些规则,比如使用沙盒。这会导致所需功能(如LSSharedFileListInsertItemURLSMLoginItemSetEnabled )失败。在这种情况下我应该如何处理?

4

4 回答 4

17

我最近经历了同样的过程,不幸的是,使用沙盒它并不像以前那么容易。我制作了一个带有非常详细说明的测试应用程序,现在在 Github 上

笔记

此演示应用程序和您的应用程序只有在它们最好部署在Xcode 调试文件夹中时才能工作,/Applications/MyGreat.app并且不能可靠地工作。

项目设置

这些是我的项目的设置,与此实现完美配合。

  1. 创建启用 ARC 的新项目
  2. 沙箱你的主应用程序和帮助应用程序(如果你还没有创建一个帮助程序,我们很快就会得到它)我还启用了代码签名
  3. 由于这只是一个测试应用程序,因此我对主应用程序或助手都没有有效的权利
  4. 如果您还没有,请创建一个帮助应用程序。转到您的项目设置并单击“添加目标”选择一个 Cocoa 应用程序。将其命名为 MyAwesomeProjectHelper 也启用了 ARC。(我将其“App Store 类别”留空)
  5. 现在选择主应用程序的目标。转到构建阶段 -> 添加构建阶段 -> 添加复制文件。
  6. 将目标更改为包装器。使子路径Contents/Library/LoginItems仅在未选中安装时保留复制。将您的助手应用程序从左侧的 Products 拖到 tableview 中。

主要应用程序代码设置

  1. 将 ServiceManagement.framework 导入您的主应用程序(不是您的助手)并包含#import <ServiceManagement/ServiceManagement.h>在您的 .h 文件中
  2. 从 Github获取 StartAtLoginController。这是 Alex Zielenski 的一个易于使用的类,用于处理添加、删除和查询登录项的复杂性。导入StartAtLoginController.h您的 h 文件。
  3. 创建您想要控制此设置的任何界面。如果您的应用程序自动启用此功能,它将被 Mac App Store 拒绝(根据指南 #2.26)
  4. 实现一个方法,例如- (IBAction)checkChanged:(id)sender我制作了一个与 StandardUserDefaults 绑定的简单复选框。(如果您选择做其他事情,您的实现可能会有所不同。)我还将复选框绑定到IBOutlet NSButton *loginCheck;以确定它的状态。这也可以通过[[NSUserDefaults standardUserDefaults] boolForKey:YourKey]
  5. 在您的 .m 文件中实现与此类似的代码。

    StartAtLoginController *loginController = [[StartAtLoginController alloc] init];
    [loginController setBundle:[NSBundle bundleWithPath:[[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"Contents/Library/LoginItems/HelperApp.app"]]]; 
    // Change "HelperApp.app" to the name of your helper
    
    if ([loginCheck state]) {
        if (![loginController startAtLogin]) {
            [loginController setStartAtLogin: YES];
        }
    } else {
        if ([loginController startAtLogin]) {
            [loginController setStartAtLogin:NO];
        }
    }
    
  6. 而已。正如您在此项目中看到的,您可能还需要使用其他一些方法,例如:

    if ([loginController startAtLogin]) {
        NSLog(@"Error");
    }
    

    用于在启用或禁用设置后检查以确保其正常工作。或这个:

    BOOL startsAtLogin = [loginController startAtLogin];
    if (startsAtLogin) {
        // Do stuff
    }
    

    如果启用了登录助手,则执行某些操作。

助手应用程序代码设置

确保在您的实现中大力测试此代码。

  1. 默认情况下,导航到位于 Supporting Files 组中的 HelperApp.plist,使您的帮助应用程序成为 UIElement。在底部添加一行键Application is agent (UIElement)YES(这将禁止应用程序在每次用户启用登录时启动时闪烁停靠图标)我还删除了界面构建器中除了 App Delegate 之外的所有内容
  2. 删除默认方法- (void)applicationDidFinishLaunching:(NSNotification *)aNotification并将其替换为- (void)applicationWillFinishLaunching:(NSNotification *)aNotification
  3. 在此方法中实现与此类似的代码。

    NSString *appPath = [[[[[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent];
    // This string takes you from MyGreat.App/Contents/Library/LoginItems/MyHelper.app to MyGreat.App This is an obnoxious but dynamic way to do this since that specific Subpath is required
    NSString *binaryPath = [[NSBundle bundleWithPath:appPath] executablePath]; // This gets the binary executable within your main application
    [[NSWorkspace sharedWorkspace] launchApplication:binaryPath];
    [NSApp terminate:nil];
    

    此代码找到您的主应用程序,确定它是二进制可执行文件(在沙箱中启动应用程序所需)打开您的应用程序,然后退出

  4. 而已。

部署

在为自己或 Mac App Store 部署应用程序时,您应该做的最后一件事是从存档项目中删除您的 Helper 应用程序。通过导航到 HelperApp 的 Target -> Build Settings -> Skip Install 并为 Release 设置 Yes。Apple 在 (http://developer.apple.com/library/ios/#documentation/ToolsLanguages/Conceptual/Xcode4UserGuide/000-About_Xcode/about.html) 提供了更多信息

于 2012-07-19T12:43:40.603 回答
3

对于沙盒应用程序,您需要创建特殊的登录项帮助应用程序(位于 Contents/Library/LoginItems 内)。在这里查看更多。另请注意,您的应用程序必须从 /Applications 文件夹启动才能正确工作登录项。

于 2012-07-18T13:23:06.197 回答
0

让您的沙盒应用程序在登录时启动的设置非常耗时,而且很容易出错。这就是为什么我制作了一个 Swift 包来自动化它。使用我的LaunchAtLogin包,您所要做的就是在 Xcode 中添加一个构建步骤,然后编写两行代码:

import LaunchAtLogin

LaunchAtLogin.isEnabled = true
于 2020-01-21T11:12:32.190 回答