问题:
XPC 似乎有自己的@try @catch 块,它在方法中捕获未处理的异常,记录异常,然后调用-[NSXPCConnection interruptionHandler]。
此问题已通过rdar://48543049 报告给 Apple。
注意:这些是不是复制和过去的解决方案,请仔细评估您的崩溃报告框架。我链接到 PLCrashReporter 的实现细节。
解决方案 A:
@try @catch 块:
- (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 (code)。所以上面的代码会将异常转发给 PLCrashReporter 异常处理程序并终止 (code) XPC。
Mattie 建议再次@throw 异常,以触发内部 XPC @catch 块以及可能的内部清理和日志记录。 这是需要考虑的事情。特别是如果您在连接的 LaunchAgent/Server 端的 NSXPCConnection 上有一个自定义的 interruptionHandler!
现在我不会再扔它了,因为 我的 XPC 是完全无状态的,崩溃应该没问题。
解决方案 A 的缺点是通过 XPC 公开的每个方法都需要这个 @try @catch 块。
解决方案 B:
使用捕获所有未处理异常的NSProxyNSXPCConnection 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;
}
解决方案 A 的所有详细信息都适用于解决方案 B。
解决方案 Z:
在 macOS 上可以使用 ExceptionHandling.framework,它的问题在BITCrashExceptionApplication.h 中有很好的概述。
讨论
如果框架未移植到 iOS,这绝不是一个好兆头。另请注意Matties 评论:
我与 Apple 的互动直接表明 ExceptionHandling.framework 不再受支持。而且,根据我在 Crashlytics 上工作的经验,它存在一些基本的互操作性问题,超出了引用 header 中所指出的问题。