问题
I'm using the latest version of the Fabric
and Fabric/Crashlytics
cocoapods (so, version 3.0.8 according to the debugger output) to integrate Crashlytics into an iOS keyboard extension. Recently, it simply stopped reporting crashes from the keyboard extension. I've checked both my code which initializes Crashlytics and the Crashlytics script build phase of my project, both are executed (and the build phase is in my keyboard extension's target).
It's hard to tell if this is related, but when I run the app I see Crashlytics try to submit crashes,
[Crashlytics:Crash:Reports] Submitting async /var/mobile/Containers/Data/PluginKitPlugin/[some-numbers]/Library/Caches/com.crashlytics.data/com.myCompnay.myApp.extension/v3/prepared/[some-more-numbers-idk-if-they're-supposed-to-be-secret].multipartmime
and then a corresponding number of messages reading
2015-06-25 09:22:33.063 com.myCompany.myApp.extension[5975:1649412] Attempted to create a task in a session that has been invalidated
leading me to believe that this is a bug in Crashlytics. The changelog for the latest version mentions an issue with background tasks
Fixed an issue that would incorrectly default to enabling NSURLSession background uploads in extensions
could this be related? Has anyone encountered and resolved this issue?
回答1:
A few minutes after posting this, it occcured to me to actually set a symbolic breakpoint on [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:]
instead of on the methods I had tried in the past. The breakpoint was hit in Crashlytics code.
To fix this, I swizzled backgroundSessionConfigurationWithIdentifer:
with a method that returns the default configuration. Implementation is below:
static Class URLSessionClass;
@implementation NSURLSessionConfiguration (FixCrashlyticsBug)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
URLSessionClass = object_getClass((id)self);
});
}
+ (NSURLSessionConfiguration *)defaultSessionConfigurationWithIdentifier:(NSString *)__unused identifer {
return [self defaultSessionConfiguration];
}
@end
@implementation CrashlyticsInterfaceManager
+ (void)startCrashlyticsFromExtension {
//Do the swizzle here instead of in load, so we don't do it in the container app as well
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
SEL originalSelector = @selector(defaultSessionConfigurationWithIdentifier:);
SEL swizzledSelector = @selector(backgroundSessionConfigurationWithIdentifier:);
Class class = URLSessionClass;
Method swizzledMethod = class_getClassMethod(class, swizzledSelector);
Method originalMethod = class_getClassMethod(class, originalSelector);
BOOL didAddMethod = class_addMethod(class,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(class,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
[Crashlytics startWithAPIKey:@"MyAPIKey"];
});
}
@end
回答2:
Clashlytics is distinguished by BundleIdentidfier, it seems to work. Main app , App Extension is a different Bundle Identifier.
In the same Bundle Identifier and Keyboard App, you will create another new project. If you set the icon for the Keyboard App Extension to the new project , it would be better. Icon will be used in Clashlytics Web page.
Install clashlytics to the newly created project, and complete. Now , it also works with the original Project. When you are finished , you can delete new project.
I worked in this way.
来源:https://stackoverflow.com/questions/31055912/crashlytics-doesnt-work-in-ios-keyboard-extension