iOS Backports

566 views

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

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

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

#3
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

#4
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

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

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

#7
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

#8
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

#9
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

#10
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

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

#12
Fortunately NSKeyedUnarchiver has convenient method to replace classes

#13
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

#14
NSString belongs to class cluster...

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

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

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

#18
There is several ways to store information in categories

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

#20
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
  5. 5. BACKPORTS
  6. 6. image: Michael image:
  7. 7. SMALL CHECKBOX
  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.lt @rolandas_razma github.com/rolandasrazm a

×