Чтобы реализовать проверку доступности
AX API (и решить
1-ю проблему):
Дополнительно к
AXAPIEnabled(), вам нужно также проверить
AXIsProcessTrusted(),
Так, если ваш код раньше выглядел вот так:
if (!AXAPIEnabled())// глобальная опция выключена?
{
// типично - предлагаем открыть панель Универсального доступа
int ret = NSRunAlertPanel (@"Accessibility API",
@"This feature requires that the Accessibility API be enabled.\nWould you like me to launch System Preferences so that you can turn on \"Enable access for assistive devices\"?",
@"OK", @"Cancel",nil);
if (ret == NSAlertDefaultReturn)
[[NSWorkspace sharedWorkspace] openFile:
@"/System/Library/PreferencePanes/UniversalAccessPref.prefPane"];
}
Для поддержки
Trust.app, код выше меняется на такой:
if (
!AXAPIEnabled()// глобальная опция выключена?
&& // and
!AXIsProcessTrusted()// процесс не имеет доверия
)
{
// предлагаем открыть панель Универсального доступа или Дать нам доверие в Trust.app
int ret = NSRunAlertPanel (@"Accessibility API",
@"This feature requires that the Accessibility API be enabled...",
@"OK", @"Cancel",nil);
if (ret == NSAlertDefaultReturn)
[[NSWorkspace sharedWorkspace] openFile:
@"/System/Library/PreferencePanes/UniversalAccessPref.prefPane"];
}
Это значит, что доверенный процесс автоматически получает доступ к
AX API, даже если глобальная опция выключена.
Для вашего удобства, мы также предлагаем использовать единую функцию
TrustIsEnabled() вместо двух
AXAPIEnabled и
AXIsProcessTrusted (см. исходный код ниже)
if (!TrustIsEnabled())// нет доверия?
{
// предлагаем открыть панель Универсального доступа или Дать нам доверие в Trust.app
int ret = NSRunAlertPanel (@"Accessibility API",
@"This feature requires that the Accessibility API be enabled...",
@"OK", @"Cancel",nil);
if (ret == NSAlertDefaultReturn)
[[NSWorkspace sharedWorkspace] openFile:
@"/System/Library/PreferencePanes/UniversalAccessPref.prefPane"];
}
Чтобы решить
2-ю проблему (безопасность в 10.5), вам нужно отметить внутренние библиотеки вашего приложения (с которыми вы слинковались используя @executable_path и обычно добавили в дополнительную фазу сборки Xcode - Copy Files) как 'Weak'; (Xcode / Дерево проекта / Targets / Имя вашей цели / Link Binary With Libraries - колонка Role для внутренних фреймворков: Измените значение с Required на Weak), далее загрузите эти библиотеки в нужном порядке в функции
main() (обычно в файле main.m) до передачи управления функции
NSApplicationMain.
Внешние библиотеки из
/System/Library/Frameworks,
/Library/Frameworks, и т. д., не требуют никаких изменений по работе.
Итак, ваш код функции
main() может выглядеть так:
int main(int argc, char *argv[])
{
NSAutoreleasePool * arp = [NSAutoreleasePool new];
NSString * selfPath = [NSString stringWithUTF8String:argv[0]];
NSString * frameworks =
[[[selfPath stringByDeletingLastPathComponent]
stringByDeletingLastPathComponent]
stringByAppendingPathComponent:@"Frameworks"];
[[NSBundle bundleWithPath:
[frameworks stringByAppendingPathComponent:
@"Growl.framework"]] load];
[[NSBundle bundleWithPath:
[frameworks stringByAppendingPathComponent:
@"Submarine.framework"]] load];
[arp drain];
return NSApplicationMain(argc, (const char **) argv);
}
Опять же, для удобства, мы предлагаем загружать библиотеки используя функцию
TrustLoadFramework. В таком случае, ваш код упрощается:
int main(int argc, char *argv[])
{
TrustLoadFramework(@"Growl.framework");
TrustLoadFramework(@"Submarine.framework");
return NSApplicationMain(argc, (const char **) argv);
}
Остаётся последняя проблема, связанная с автоматическим обновлением вашего ПО:
Проблема заключается в том, что система доверия
AX API очень недоверчивая и нервная, и в том случае, если обнаруживаются модификации исполняемого файла, доверие отзывается. Во время обновления ПО изменения исполняемых файлов происходят практически неизбежно.
Однако, вы можете легко подстроиться под такое поведение, вызвав функцию
TrustUpdate() в начале функции
main():
int main(int argc, char *argv[])
{
TrustUpdate();
TrustLoadFramework(@"Growl.framework");
TrustLoadFramework(@"Submarine.framework");
TrustLoadFrameworkFromFolder(@"MyPrivate.framework",
@"MyPrivateFrameworks");
if (TrustIsEnabled())
NSLog(@"I'm trusted Application!");
return NSApplicationMain(argc, (const char **) argv);
}
TrustUpdate проводит проверку, просит модуль Trust поднять уровень доверия к вашему приложению, и, если это возможно, перезапускает приложение.