Проблема:
Кажется, что XPC имеет свой собственный @ try @catch block , который перехватывает необработанные исключения внутри метода, регистрирует исключение и затем вызывает -[NSXPCConnection interruptionHandler]
.
Об этой проблеме сообщается в Apple по адресу rdar: //48543049.
ПРИМЕЧАНИЕ: Это , а не copy &прошлые решения, тщательно оцените свою структуру отчетности о сбоях.Я ссылаюсь на детали реализации PLCrashReporter .
Решение A:
@ try @catch block :
- (void)upperCaseString:(NSString *)aString withReply:(void (^)(NSString *))reply {
@try {
NSArray *array = [NSArray array];
reply([array objectAtIndex:23]);
} @catch (NSException *exception) {
NSUncaughtExceptionHandler *handler = NSGetUncaughtExceptionHandler();
if (handler) {
handler(exception);
}
}
}
Обсуждение
HockeyApp использует PLCrashReporter для отчетов о сбоях. PLCrashReporter регистрирует NSUncaughtExceptionHandler
( код ).Таким образом, приведенный выше код перенаправит исключение в обработчик исключений PLCrashReporter и завершит ( code ) XPC.
Мэтти предлагает снова @ throw исключение, чтобы вызвать внутренний блок XPC @ catch и возможную внутреннюю очистку и ведение журнала. Это то, что нужно учитывать .Особенно, если у вас есть пользовательский interruptionHandler
на NSXPCConnection
на стороне LaunchAgent / Server соединения!
Пока я не собираюсь снова его бросать, потому что мой XPC полностью лишен состояния и должен работать только после сбоя.
Недостаток Решение A заключается в том, что каждый метод, предоставляемый через XPC, требует @ try @catch block .
Решение B:
Используйте NSProxy
, который перехватывает все необработанные исключения как NSXPCConnection exportObject
:
@interface LOUncaughtExceptionHandlerProxy : NSProxy {
NSObject *_object;
}
@end
@implementation LOUncaughtExceptionHandlerProxy
- (instancetype)initWithObject:(NSObject *)object
{
NSParameterAssert(object);
_object = object;
return self;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
return [_object methodSignatureForSelector:selector];
}
- (void)forwardInvocation:(NSInvocation *)invocation
{
@try {
[invocation invokeWithTarget:_object];
} @catch (NSException *exception) {
NSUncaughtExceptionHandler *handler = NSGetUncaughtExceptionHandler();
if (handler) {
handler(exception);
}
}
}
@end
Настройка в приемнике NSXPCListener
:
- (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection {
XPC *exportedObject = [XPC new];
LOUncaughtExceptionHandlerProxy *proxy = [[LOUncaughtExceptionHandlerProxy alloc] initWithObject:exportedObject];
newConnection.exportedObject = proxy;
newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(XPCProtocol)];
[newConnection resume];
return YES;
}
Все детали Solution A относятся к Solution B .
Solution Z:
В macOS можно использовать ExceptionHandling.framework, проблемы с ним очень хорошо изложены в BITCrashExceptionApplication.h .
Обсуждение
Это никогда не является хорошим признаком, когдафреймворк не портирован на iOS.Также обратите внимание Matties комментарий:
У меня были взаимодействия с Apple, которые прямо указывают на то, что ExceptionHandling.framework больше не поддерживается.И, по моему опыту, работая над Crashlytics, у него были некоторые фундаментальные проблемы взаимодействия, помимо того, что указано в указанном заголовке .