I ran into this runtime error the other day when testing a Ruby Motion app on a device with iOS 5.1 installed:
-[__NSArrayI objectAtIndexedSubscript:]: unrecognized selector sent to instance
Everything had been working fine in iOS 6 and, previously, when testing in iOS 5.x. The change that introduced this issue was upgrading a vendored version of the Objective-C SDWebImage library. In the latest version, the developers started using indexer syntax on NSArray, which allows one to access the contents of an NSArray like this:
arr instead of the old syntax:
As our team was using the iOS 6.0 SDK, compiling this code wasn’t an issue. The root of our problem was that
arr is effectively translated into
[arr objectAtIndexedSubscript:2] at compile time. The
- objectAtIndexedSubscript: method is implemented in iOS 6 on
NSArray to behave just like
objectAtIndex:. However, as we discovered earlier, it is not implemented in iOS 5.x.
After some digging, I learned that this is usually not an issue when compiling an app with ARC support using the 6.0 SDK due to the inclusion of the
libarclite library at link time. This library, among other things, provides a shim implementation of
[NSArray objectAtIndexedSubscript:]. By passing the flag
-fobjc-arc during the link phase, this library will be included.
Now our problem was Ruby Motion doesn’t currently use the
-fobjc-arc flag during linking unless the deployment target is less than 5.0. But, I found a way to sneak a flag into the link phase:
1 2 3 4 5
Motion::Project::App.setup do |app| ... app.libs << "-fobjc-arc" ... end
With this in place, we were back up and running on iOS 5.x and 6.0.
rake --trace was very useful for seeing all the commands being run (and verifying the inclusion of
-fobjc-arc) thanks to Ruby Motion’s diligent use of the