Swizzling NSBundle for reskinnable demo

322 views Asked by At

I'm trying to build an application (not for app store distribution) that can be reskinned by downloading a bundle containing images and strings files.

For localization, I've had no problems swizzling localizedStringForKey:value:table: to load my custom strings, however for images I have much more trouble.

My project is using storyboards without asset catalogs and targets iOS 7. I've tried swizzling the following methods on NSBundle to capture image loading from a storyboard, but none of them are hit (at least for png files):

URLForResource:withExtension:
URLForResource:withExtension:subdirectory:localization:
URLsForResourcesWithExtension:subdirectory:

I do see attempts to load .car files (this is the asset catalog format) however these return a nil URL. I've also attempted to swizzle the pathForResource: versions of the above methods, but no new calls are captured.

Any ideas?

1

There are 1 answers

0
Tim On BEST ANSWER

I gave up trying to intercept requests for individual image files in NSBundle and switched over to the asset catalog system. The URLForResource methods in NSBundle are called and always look for Assets.car, simply returning Assets.car from my own bundle caused my custom images to be loaded. This works for [UIImage imagedNamed:] as well as loading from nibs.

For completeness sake, to generate an asset catalog you need to use actool located in XCode.app. I used actool for the simulator and copied the command from the build log (this catalog also worked on my iPhone 5S...):

actool --platform iphonesimulator --minimum-deployment-target 7.0 --target-device iphone --compress-pngs --compile  [path_to_output_bundle] [path_to_xcassets]

Both of the paths have to been absolute paths otherwise actool fails.