Reputation: 1229
I'm trying to debug a mysterious crash I'm seeing in Crashlytics, but haven't been able to reproduce myself.
The error message looks like this:
Fatal Exception: NSInvalidArgumentException
-[NSNull compare:]: unrecognized selector sent to instance 0x1e911bc30
-[NSOrderedSet initWithSet:copyItems:]
Here is the full stacktrack if interested
Because I haven't been able to pinpoint the origin of the crash, I thought I would add a new method to NSNull
in order to further debug it via logging.
However I'm not sure how to do it. I think I'd need to add a compare
method to NSNull
, but I have limited knowledge of objc. I got the idea from this answer. The proposed solution for a similar problem looks like this
BOOL canPerformAction(id withSender) {
return false;
}
- (void)viewDidLoad {
[super viewDidLoad];
Class class = NSClassFromString(@"UIThreadSafeNode");
class_addMethod(class, @selector(canPerformAction:withSender:), (IMP)canPerformAction, "@@:");
}
How could I do this in Swift for adding compare
to NSNull
?
Upvotes: 1
Views: 793
Reputation: 163288
You could add a compare
method to NSNull
like this:
Objective-C:
#import <objc/runtime.h>
static inline NSComparisonResult compareNulls(id self, SEL _cmd, NSNull *other) {
if([other isKindOfClass:[NSNull class]]) {
return NSOrderedSame; // Nulls are always the same.
}
return NSOrderedDescending;
}
@implementation NSNull (Comparisons)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
const char *encoding = [[NSString stringWithFormat:@"%s@:@", @encode(NSComparisonResult)] UTF8String];
class_addMethod([self class], @selector(compare:), (IMP)compareNulls, encoding);
});
}
@end
Swift:
// Add this code to your AppDelegate.swift file:
import ObjectiveC
fileprivate func compareNulls(_ self: AnyObject, _ _cmd: Selector, _ other: AnyObject) -> ComparisonResult {
if other is NSNull {
return .orderedSame
}
return .orderedDescending
}
fileprivate func addNSNullCompareImplementationIfNecessary() {
let sel = NSSelectorFromString("compareNulls:")
guard class_getMethodImplementation(NSNull.self, sel) == nil else {
return
}
let types = "i@:@"
class_addMethod(NSNull.self, sel, imp_implementationWithBlock(compareNulls), types)
}
// Add this line to your -didFinishLaunching: function:
addNSNullCompareImplementationIfNecessary()
This is only a temporary solution that will stop the crashes.
I would nevertheless encourage you to a) file a bug report, and b) continue investigating why this happened - clearly having an NSNull
in this case wasn't expected by Parse...
Upvotes: 1