iOS Backports


Published on

Cocoa Kucha talk at @NSLondonMeetup about iOS backports. Whats that, why you should use them and example of base internationalisation backport to iOS5

I am iOS developer from before official iOS SDK times and I have seen how it grow and evolves

Time to time Apple release new version of iOS SDK. All those new features that will open up new possibilities

But those other people - you know - like your boss for example, doesn’t understand that time you will waste to support multiple iOS versions will be more expensive than those 3 users that still didn’t updated

So you stuck for a few years supporting 2 or 3 versions of SDK writing spaghetti code, checking if class or method exist to use different code paths

Backports to the rescue! No spaghetti code, no checking for methods or class existence, no impact on users who already updated

Good backport is a runtime hook and have no implications on SDK’s that supports functionality natively

It’s not that hard to implement if you know what you doing and it will make your app code way cleaner and more maintainable in a long term

Can everything be backported? Most likely yes, but sometimes it could be more complex than the app itself and it would be a waste of time. On the other hand it could be few lines of code and could do things that would be extremely difficult to do otherwise

I made few of those, maybe you used some, maybe not, but nevertheless I think it’s insanely cool, and I use them in apps I write

For example, base internationalisation backport. You know - that small checkbox in Xcode that makes you life as developer way brighter if you making multilingual applications

If you launch App on iOS5 witch doesn’t support base internationalisation you will see NSUnarchyver error that NSLocalizableString doesn’t exist

Fortunately NSKeyedUnarchiver has convenient method to replace classes

Next, you have to extract info passed into -[RRLocalizableString initWithCoder:]. There is no easy way to find out -[NSCoder decodeObjectForKey:] keys, but the best way I found is to swizzle it

NSString belongs to class cluster...

by swizzling -[NSCoder decodeObjectForKey:] you will find NSKey and NSDev to use in -[NSBundle localizedStringForKey:value:table:], but we still missing “table”.

Unfortunately there is no public method on NSCoder to wind out what file we unarchiving

Most file operations use -[NSBundle pathForResource:ofType:] and sure enough swizzling it gives path we need. All we have to do is store it

There is several ways to store information in categories

All what was needed to make this complicated looking backport was several lines of code

there is no reason to write hard maintainable code just to support older SDK’s, so I invite everyone to check out my backports on github and write some of their own

Published in: Technology, Business
  • Be the first to comment

  • Be the first to like this

iOS Backports

  1. 1. BACKPORTS Rolandas Razma image: Holger
  2. 2. image: Audi
  3. 3. image: Jenny
  4. 4. image: ken
  6. 6. image: Michael image:
  8. 8. [NSKeyedUnarchiver setClass: [RRLocalizableString class] forClassName: @"NSLocalizableString"]; image: Angela
  9. 9. image: Johan Wieland
  10. 10. image: European Southern Observatory
  11. 11. - (id)initWithCoder:(NSCoder *)aDecoder { if( (self = [super init]) ){ _stringsFileKey = [aDecoder decodeObjectForKey:@"NSKey"]; _developmentLanguageString = [aDecoder decodeObjectForKey:@"NSDev"]; } } return self; - (id)awakeAfterUsingCoder:(NSCoder *)aDecoder { return [[NSBundle mainBundle] localizedStringForKey: _stringsFileKey value: _developmentLanguageString table: ??currentNibName??]; } image: Don J Schulte
  12. 12. image: Tom Gill
  13. 13. -[NSBundle pathForResource:ofType:]
  14. 14. image: Dan Iggers
  15. 15. - (id)initWithCoder:(NSCoder *)aDecoder { if( (self = [super init]) ){ _stringsFileKey = [aDecoder decodeObjectForKey:@"NSKey"]; _developmentLanguageString = [aDecoder decodeObjectForKey:@"NSDev"]; } return self; } - (id)awakeAfterUsingCoder:(NSCoder *)aDecoder { return [[NSBundle mainBundle] localizedStringForKey: _stringsFileKey value: _developmentLanguageString table: [NSBundle currentNibName]]; }
  16. 16. @rolandas_razma a