之前我们实现程序开机启动一般都是通过LSSharedFileList.h中的相应的方法将程序写入到启动项中。但在沙盒模式下因为权限的问题就再也不能实现这样的功能了,现在找到了一个新的方法来实现SandBox下的开机启动。
1.引入ServiceManagement.framework
2.创建一个新的Target,模块为一般的CocoaApplication就行了(称它为Helper吧)
3.在该Helper的Info中设置Application is background only(最好让它一个Window也没有)
4.在主程序中设计CopyFiles如下:
5.为防止Helper签名错误,在主工程中的Strip Debug Symbols During Copy都设置为No,如下:
6.解决Xcode 在提交时会出现错误“xxx does not contain a single–bundle application or contains multiple products” archive错误,所以需要设置Helper工程中的Skip Install ,如图:
7.在你需要设置开机启动的地方使用代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
NSString
*helperPath = [[[
NSBundle
mainBundle] bundlePath] stringByAppendingPathComponent:
@"Contents/Library/LoginItems/yourHelper.app"
];
if
(![[
NSFileManager
defaultManager] fileExistsAtPath:helperPath])
{
return
;
}
NSURL
*helperUrl = [
NSURL
fileURLWithPath:helperPath];
// Registering helper app
if
(LSRegisterURL((
__bridge
CFURLRef
)helperUrl,
true
) != noErr)
{
NSLog
(
@"LSRegisterURL failed!"
);
}
// Setting login
// com.xxx.xxx为Helper的BundleID,ture/false设置开启还是关闭
if
(!SMLoginItemSetEnabled((
CFStringRef
)
@"com.xxx.xxx"
,ture))
{
NSLog
(
@"SMLoginItemSetEnabled failed!"
);
}
|
8.你的Helper的代码便是充当一个主程序的启动器角色,但注意以下的代码是获取的主程序的可执行文件,否则会出现SandBox的错误,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
NSString
*appPath = [[
NSBundle
mainBundle] bundlePath];
appPath = [appPath stringByReplacingOccurrencesOfString:
@"/Contents/Library/LoginItems/Helper.app"
withString:
@""
];
appPath = [appPath stringByAppendingPathComponent:
@"Contents/MacOS/mainApp"
];
if
(![[
NSFileManager
defaultManager] fileExistsAtPath:appPath])
{
return
;
}
NSArray
*runningArray = [
NSRunningApplication
runningApplicationsWithBundleIdentifier:
@"com.xxx.mainapp"
];
if
([runningArray count] > 0)
{
return
;
}
[[
NSWorkspace
sharedWorkspace] launchApplication:appPath];
|
注意事项:你的主程序必须在Application的目录下,开机启动的设置才会生效,否则会失败。