Mac os上App開機自動啟動
Mac OS上執行的App,想要支援使用者登入後App自動啟動的功能,可以使用Service Management Framework 或 Shared File List實現。對於沙箱開啟的應用,蘋果推薦的做法是使用Service Management Framework;對於沙箱未開啟的應用,蘋果推薦使用Shared File List。Service Management Framework對於沙箱未開啟的APP也是可以實現登入後自動啟動的。
本文將介紹通過Service Management Framework來實現App自定啟動的方法。基本方式是建立一個輔助啟動的"Helper Application",將其註冊到系統中,在使用者登入後通過它來啟動主App。
The Helper App
在工程中新增一個Cocoa Application型別的target。
刪除AutoLaunchHelper中無用的內容:
- 移除ViewController.h和ViewController.m
- 移除Main.storyboard中ViewController
- 移除Main.storyboard中WindowController
AutoLaunchHelper的Info.plist中,將Application is background only設定為 Yes。
在AutoLaunchHelper的AppDelegate.m中新增程式碼,用來啟動主App。
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { NSArray<NSRunningApplication *> *runningApps = [[NSWorkspace sharedWorkspace] runningApplications]; __block BOOL isRunning = NO; [runningApps enumerateObjectsUsingBlock:^(NSRunningApplication * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if ([obj.bundleIdentifier isEqualToString:@"your.domain.AutoLaunchMain"]) { isRunning = YES; *stop = YES; } }]; if (!isRunning) { NSArray<NSString *> *pathComponents = [[[NSBundle mainBundle] bundlePath] pathComponents]; NSMutableArray *mutablePathComponents = [[NSMutableArray alloc] initWithArray:pathComponents]; [mutablePathComponents removeLastObject]; [mutablePathComponents removeLastObject]; [mutablePathComponents removeLastObject]; [mutablePathComponents addObject:@"MacOS"]; [mutablePathComponents addObject:@"AutoLaunchMain"]; NSString *mainAppPath = [NSString pathWithComponents:mutablePathComponents]; [[NSWorkspace sharedWorkspace] launchApplication:mainAppPath]; } }
在AutoLaunchHelper的Build Settings中,將Skip Install設定為Yes。
檢視沙箱設定,預設情況下,沙箱是開啟的。
注:保證AutoLaunchHelper和AutoLaunchMain沙箱設定是相同的,都開啟或者都關閉,否則影響執行效果。
Main App
AutoLaunchMain target中新增ServiceManagement庫
進入AutoLaunchMain的AppDelegate.m檔案,新增如下程式碼。通過SMLoginItemSetEnabled方法啟用AutoLaunchHelper。
#import "AppDelegate.h"
#import <ServiceManagement/ServiceManagement.h>
@interface AppDelegate ()
@property (nonatomic, strong) NSStatusItem *statusItem;
@end
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// 啟動後在狀態列顯示“AutoLaunchMain”
self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
self.statusItem.button.title = @"AutoLaunchMain";
// 啟用AutoLaunchHelper
CFStringRef aCFString = (__bridge_retained CFStringRef)@"your.domain.AutoLaunchHelper";
SMLoginItemSetEnabled(aCFString, true);
CFRelease(aCFString);
}
為驗證自動啟動是否生效,給AutoLaunchMain在狀態列添加了名字為AutoLaunchMain的按鈕。機器重啟使用者登入後,狀態列有AutoLaunchMain名字的按鈕顯示,證明自動成功,否則自動啟動失敗。
為AutoLaunchMain target新增Copy Files Phase。
具體設定為:
- Destination: Wrapper
- Subpath: Contents/Library/LoginItems
- 新增helper.app檔案
檢查AutoLaunchMain的沙箱設定,保證AutoLaunchHelper和AutoLaunchMain沙箱設定是相同的。
測試
1. 編譯AutoLaunchMain
2.在Finder中找到編譯結果AutoLaunchMain.app
3.雙擊AutoLaunchMain.app啟動主應用,啟動成功後狀態列中顯示AutoLaunchMain按鈕
4.重啟Mac,使用者登入後,檢視狀態列是否有AutoLaunchMain按鈕,有表示自動啟動成功,否則表示自動啟動失敗。