Software Engineer

I am a Software Engineer. I have a Bachelor (Honours) of Science in Information Technology from the University of Sunderland - Class of 2003. I have been developing software since 2001 when I was offered a role at CERN as part of their Technical Student Programme.

By 2016 I had grown really tired of the software industry and by the end of 2019 Apple killed whatever excitement I had left. I am not sure what the next 10 years will bring. What I do know is that my apettite to do work that is impactful has only grown bigger and stronger. Great people make me tick more than anything.

I am also tired.

How to debug a "class JKserializer is implemented in both" case (Part 1)

Recently came across the following warning while running an app on the simulator.

objc[3946]: Class JKSerializer is implemented in both **/Users/qnoid/Library/Application Support/iPhone Simulator/5.1/Applications/9CEF83D3-C9DE-4951-95DF-CC1A3DB223F8/TBUndefined.app/TBUndefined** and **/Users/qnoid/Library/Application Support/iPhone Simulator/5.1/Applications/9CEF83D3-C9DE-4951-95DF-CC1A3DB223F8/TBUndefined.app/TBUndefined**. One of the two will be used. Which one is undefined.

The thing to note is how the warning points to the exact same location. Specifically the TBUndefined executable. What this means is that the class definition somehow found its way twice in the executable.

A seemingly random crash would also occur when calling NSDictionary#JSONString. Random as in, every now and then the app would be in a state where it would crash. But once in this state, the crash was consistently reproduced. In both cases, the warning above was depicted.

When the crash occurred, the following error was emitted in the console.

2013-02-11 22:57:19.754 TBUndefined[3946:c07] +[JKSerializer serializeObject:options:encodeOption:error:]: unrecognized selector sent to class 0x5bca4

This is seemingly contradictory to the warning. On one hand the JKSerializer class appears to be defined twice. While on the other, one of its method definition is missing.

First thing to do is find where the JKSerializer class is defined. Turns out, this class is part of JSONKit under the JSONKit.m file along with the expected method definition. (It’s worth noting that JSONKit was compiled as a static library, part of a set of dependencies as defined using Cocoapods)

At this point decided to take a look at the executable itself for the definition of JKSerializer. Steve Nygard has created a great tool, class-dump, that generates declarations of classes, protocols and categories in a Mach-O file.

The executable can be found at

/Users/qnoid/Library/Developer/Xcode/DerivedData/TBUndefined-dksnnnn-dsvgfybkturbkhxboi-b/Build/Products/Debug-iphonesimulator/TBUndefined.app/TBUndefined

Running a

	class-dump TBUndefined > TBUndefined.dump

and searching for JKSerializer under TBUndefined.dump we do find the two definitions as hinted by the warning. Take a look at the methods.

First Occurrence

	@interface JKSerializer : NSObject
	/* properties omitted for brevity */

	  + (id)serializeObject:(id)arg1 options:(unsigned int)arg2 encodeOption:(unsigned int)arg3 block:(id)arg4 delegate:(void)arg5 selector:(id)arg6 error:(SEL)arg7;

	/* instance methods omitted for brevity */
	  
	@end

Second Occurrence

	@interface JKSerializer : NSObject
	  
	/* properties omitted for brevity */

	  + (id)serializeObject:(id)arg1 options:(unsigned int)arg2 encodeOption:(unsigned int)arg3 error:(id *)arg4;

	/* instance methods omitted for brevity */

	@end

As you can tell, the method in question, appears to have a different definition to the one the code is calling. Having 3 extra arguments, block:delegate:selector:.

	+ (id)serializeObject:options:encodeOption:block:delegate:selector:error:;

Turns out, this is the JSONKit 1.5 definition.

In the next part, we’ll see how that definition ended up there and explain the randomness of the crash.

I have created a sample project that demonstrates the above behaviour as a reference.

Kudos

mikeash for contributing so much valuable knowledge to the community for free via his blog.
alloy for creating Cocoapods.