Monthly Archives: July 2014

2012 V244 Internationalization Tips and Tricks

+ currentLocale: returns static object that doesn’t change
+ autoupdatingCurrentLocale: picks up any changes to dateformat settings, time to show in 12h format, etc.
NSCurrentLocaleDidChangeNotification: when the settings change, received this notification the UI should update to new locale

Localising Text
Generating Strings entries from source files
find . -name \*.m | xargs genstrings -o en.lproj/

Searches for NSLocalizedString(@”key”, @”description”) and translates to:
/* description */
“key” = “key”

instead of -compare: use -localizedStandardCompare:

avoid -[NSString rangeOfString:] does not take into account user local it uses system local.
use -[NSString rangeOfString:options:range:locale:] passing currentLocale or the autoUpdatingCurrentLocale

Arabic being RTL can contain LTR text e.g: Brand names
Visually text is shown RTL but when the string is stored in memory it is stored in a single logical order LTR. When searching through string character by character or word by word. This directionality needs to be taken in consideration

Not all characters fit in a unichar. Affects when using methods like character at index.


Custom Macros
ITTRootViewControllerString(@"key", @"description");
NSString* ITTRootViewControllerSTring(NSString *key, NSString *comment){
NSBundle *b = [NSBundle mainBundle];
NSString *str = [b localizedStringForKey:key value:nil table:@"ITTRootViewController"];
str = ITTPseudolocalize(str);
return str;

Pseudolocalize: Rewrite the string with any type of mark to be sure the text has been localised e.g: My lovely label -> $$My lovely label$$

easiest way to convert a date into a string:

NSDateFormatter *df
[df setDateFormat:@"M/dd/yyyy"];

this is correct only in some countries
[df setDateStyle:NSDateFormatterShortStyle];

If you only want to show the month of a date:
[df setDateFormat:@"MMM d"];
NSString *format = [NSDateFormatter dateFormatFromTemplate:@"MMM d" options:0 locale:[NSLocale currentLocale]];
[df setDateFormat:format];

follows: Unicode Standard 35

Parsing Date String
Tell the dateformatter what calendar is being used. NSCalendar
strptime_l parse a timestamp to a time interval which can be formatted by the calendar

Add timezone to the dateformatter: [df setTimeZone:[NSTimeZone timeZoneWithSecondsFromGMT:0]]

NSTimeZone: instead of being relative to a specific point in time it is relative to coordinated universal time.

Portions of a calendrical date, the various parts of the formatted human readable date

Unit lengths
- [NSCalendar maximumRangeOfUnit:] How many months
- [NSCalendar rangeOfUnit:inUnit:forDate:] how many days are in that month

Use @”j” for formatting an hour
[NSDateFormatter dateFormatFromTemplate:@"j" options:0 locale:[NSLocale currentLocale]];

US: h a (1-12 am)
Japan: H (0-23 withouth am)
France: HH (00-23 without am)
China: ah (am before 1-12)

Localizing Numbers

Parsing Numbers
-intValue, scanf, etc
NSNumberFormatter *nf
[nf setNumberStyle:NSNumberFormatterDecimalStyle];

+stringWithFormat:, printf, etc
[NSNumberFormatter localizedStringFromNumber:myNumber numberSTyle:setNumberStyle:NSNumberFormatterDecimalStyle];
Will use the correct character set for arabic

[nf setNumberStyle:NSNumberFormatterCurrencyStyle];

No unit conversion but NSLocale can tell you what currency/unit should be used
Unlocalized numbers strto*_l for the same purposes as the NSCalendar

[UIImage imageNamed]; Uses NSBundle and this one takes the language into account

2013 V219 Making Your App World-Ready

Use Base Internationalization
– Edit only one set of nib files
– String file is generated for each storyboard and nib file
– localizers only need to edit the strings file
– use autolayout with base internationalization

ibtool generates a strings file for you. When a nib file has changed, inside the Base.lproj folder:
ibtool ChangeNib.xib –generate-strings-file NewStrings.strings

New in iOS7
stringsdict to take into account plurality and/or gender
Localized propertylist:
result = [NSString localizedStringWithFormat:NSLocalizedString(@”%d file(s) remaining”, @”comment”, n] -> research more on this check foundation release notes and What’s new in Cocoa WWDC 2013

Run the app with the argument
-AppleLanguages "(Korean)"

NSDataDetector to detect phone numbers, Addresses, make them into links

2014 V201 Advanced topics in internationalization
Language and Region Settings
– Primary language
– Specify preferred languages in order
– User can specify preferred language although it isn’t available in the OS but your app can be localised with that language
– Specify the region independently of the localization

iOS8 – when the text encoding type is not provided it can be abled to guess with the API
+ (NSStringEncoding) stringEncodingFromData:(NSData *)data
encodingOptions:(NSDictionary *)opts
convertedString:(NSString **)string
usedLossyConversion:(BOOL *)usedLossyConversion

iOS8 – NSDateComponentsFormatter
For displaying duration or amounts of time (1 hour, 50 minutes)

iOS8 – NSDateIntervalFormatter
For displaying time intervals (9:00 AM – 4:30 PM)

iOS8 – NSEnergyFormatter, NSLengthFormatter, NSMassFormatter

iOS8 – Formatting Context
Tells how the formatted text should be written, depending on how and where it appears:
– NSFormattingContextStandAlone
– NSFormattingContextListItem
– NSFormattingContextBeginningOfSentence
– NSFormattingContextMiddleOfSentence
– NSFormattingContextDynamic, once it is inserted in the formatted string it resolves beginning, middle of sentence.

In case you need to know the language the app is running because you want to show something running in Japanese but not in english. Put a localised resource in the NSBundle with value YES or NO on the required resource

Locale Change eg
- (void userChangeLocale: (NSNotification *) notification{
myFormatter.locale = [NSLocale currentLocale];
myFormatter.dateFormat = [NSDateFormatter dateFormatFromTemplate: myTemplate option:0 locale:myFormatter.locale]

[myView setNeedsDisplay];

Don’t assume “First Last”
NSString *displayName = [NSString stringWithFormat:@"%@ %@", firstName, lastname];
Use when used with Addressbook
NSString *diplayName= (NSString *) ABRecordCopyCompositeName(record);
When not form the Addressbook
ABRecordRef record = ABPersonCreate();
ABRecordSetValue(record, kABPersonFirstNameProperty, (CFStringRef) firstName, NULL);
ABRecordSetValue(record, kABPersonLastNameProperty, (CFStringRef)lastName, NULL);
NSString *displayname = (NSString *)ABRecordCopyCompositeName(record);

[textView setAlignment:NSTextAlignmentLeft]
[textView setAlignment:NSTextAlignmentNatural]

Text Directionality
[textField setBaseWritingDirection: NSWritingDirectionRightToLeft forRange:range];
[textField setBaseWritingDriection: NSWritingDirectionNatural forRange:range];
This guesses the directionality of the text, analyses the first characters and decides the direction.
In case this can not be used, because text is actually in arabic but begins with LTR letter: need to insert invisible character/mark that indicates the direction:
LRM: U+200E
RLM: U+200F

ios 6
In Scheme->Options->Aplication Language -> Right to Left Pseudo-Language

To make Keyboard and other UI Elements move in tandem, informatino we have:

Specify KeyboardType as not all Locales are going to show the same characters

Some localizations like chinese, the user types in the phonetic representations, the predictable text shows the options and then the user selects the correct option. This is indicated with -markedTextRange if it exists most likely the live search or similar won’t work as the typed in text is not the final text the user wants to input.

2014 V201 Localising with Xcode6
Export/import xliff format
Preview localizations

Recap for project
– use comments on NSLocalizedString
– use a different strings file per ViewController/Screen
– Pseudolocalize with macros
– use .stringsdict for plurals and gender control good resource
– listen to localeDidChange notification or use +[NSLocale autoupdatingCurrentLocale]. What should be done:
1)Listen to NSCurrentLocaleDidChangeNotification
2) If you keep formatters/locales around, use +[NSLocale autoupdatingCurentLocale]
3) Redo template formats
4) Invalidate any active views that contain locale-derived information
– ABRecordRef to display names
– Right-To-Left use: [textView setAlignment:NSTextAlignmentNatural]
– Directionality use: [textField setBAseWritingDriection: NSWritingDirectionNatural forRange:range]; With LRM/RLM marks

To use Dynamic Type in custom labels:
use preferedFontForTextStyle

iOS 8 CellSizing
First the tableview uses an estimated cell size. Once the cell needs to be displayed in screen:
1) Create Cell
2) Size cell
3) Update contentsize
4) Display cell

Self-sizing Cells
– Using Autolayout, if constraints are determined unambiguously nothing needs to be done, the autolayout engine returns back the correct size.


– Manual-sizing: override -sizeThatFits:

– use tableView.estimatedRowHeight instead of rowHeight
– If tableView comes from nib file or story board. RowHeight will be set when it comes out of the nib so you need to set: tableView.rowHeight = UITableViewAutomaticDimension. this is the new default rowHeight.

Differences with iOS 7 on Dynamic sizing for Cells
This was called for ALL the cells on creation of the table view. So if we have 22000 cells to display this was called that many times. Cell size was difficult to provide, as the cell wasn’t created yet.

Works with estimated cell height, once the cell is about to be displayed on screen then the real size is calculated and can even be retrieved automatically from AutoLayout.

Self-sizing Cells in CollectionView FlowLayout
Very similar to table view using size instead of only height.
estimatedItemSize instead of itemSize.

High-performance Layouts
iOS7 introduced invalidation contexts. Flow layout uses this for rotation, in iOS 8 used for self-sizing cells

iOS 8 improves on:
– floating headers
– avoid visual jumps with self-sizing cells

TODO: Research more about Invalidation contexts


Screen Shot 2014-07-22 at 12.30.52


Screen Shot 2014-07-22 at 12.08.55


UICollectionViewLayoutAttributes (some)
– Position
– Size
– Opacity
– zIndex
– Transform
– …

Customization of Layout
– Size
– line spacing
– Inter cell spacing
– Scrolling direction
– Header Footer size
– Section inset

– Want single line -> play with insets

Supplementary views are data driven
Decoration views are layout driven -> independent from the data e.g: Background

Carries information from a Layout to a Collection view and gets supplied to all the views in the collection view. One instance per view. Attributes: center, size, frame, alpha, transform, zIndex (to indicate how cells are stacked on top of each other)

Layout that get information from the CollectionViewDelegate

– When a change is done in a layout, the layout gets invalidate via -invalidateLayout
– If you want to change a a property on the layout but you want it to be done with animation performBatchUpdates:completion: to begin updates and end updates on a TableView (CollectionView). E.g: Item size on the layout
– CoverFlow we want to change transforms the view which means changing layout attributes, respond to method shouldInvalidateForBoundsChange: Flowlayout implements this method on the rotation of the device

When implementing a CollectionView with custom Layout, think first if it can be solved by sublcassing UICollectinViewFlowLayout

– Customise and add new kinds of views (decoration view, etc)
– Tweak layout attributes: To transform, alpha, etc.
– Add new layout attributes. Subclassing UICollectionViewLayoutAttributes to add additional layout attributes. E.g: to adjust some visual property on the cell to depend on the column.
– Gesture support, gesture to a specific cell.
– Custom insert and delete animations

Fully customizing UICollectionViewLayout
UICollectionViewLayout is an abstract class that needs to be extended in order to create a custom layout

Required overrides
- collectionViewContentSize
tells the user scrollable area in the collection view, where the content is going to be layout
- layoutAttributesForElementsInRect:
called to ask how to lay things out returns an array of LayoutAttributes
- layoutAttributesForItemAtIndexPath:
Additionally sometimes this is required as well.
- layoutAttributesForSupplementaryViewOfKind:atIndexPath:
- layoutAttributesForDecorationViewOfKind:atIndexPath:

Order of operation to call those methods
– prepareLayout
to do upfront calcs for layout e.g: circle layout, etc.
– others
invalidateLayout (like in coverflow, when sizes need to change. Says to collection view to start over again)
– cycle continues

Strategy for great Work V237
What I take with me:
– A good engineer knows when to ask for help
– Knows where is your boundaries of knowledge
– Knows when to simplify
– when to copy/inspire in others work.
– Failure is ok
– Choose the simplest thing which might work
– Only show your best work don’t show the second best one
– Separate yourself from your work. Accept Criticism
– Work should explain itself

Design Information Flow (Truth, derived value, creation of new truth)

Think about of system in terms of how information is moving through. Considering first where is truth, who really knows that state.

Derived values
– It computes from inputs
– Needs to recompute when input change
Similar to a cache (not so sure about this one… cache doesn’t recompute with input changes?!)
let the model control the derived values
– Create new truth for updating model, creating a working copy of the original model. Once the “suggested” changes are validated, they are copied over to the original one.

Define Clear Responsibilities and use composition of smaller peaces that hold responsibility inside a bigger responsibility

Simplify with Immutability.
Mutability increases dependencies, object references moving through different controllers makes those controllers dependant on how they work with the object

Swift Structs are passed by value to functions, an implicit copy is made.

New in iOS8

new “AlertViews” and “ActionSheets” are presented using UIAlertController

UIAlertController *sheet = [UIAlertController alertControllerWithTitle:...];
[sheet addAction:[UIAlertAction actionWithtTitle:@"Reply"
style:UIAlertActionStyleDefault handler:^void (UIAlertAction *action){


[self presentViewController:sheet ...];

New UISearchController

MyResultsController *resultsController = [[MyResultsController alloc] init];

UISearchController *searchController = [[UISearchController alloc] initWithSearchResultsController:resultsController];
searchController.searchResultsUpdater = resultsController;
self.tableView.tableHeaderView = searchController.searchBar;
self.definesPresentationContext = YES

Tells the searchController where to present the resultsController. If this one is not defined, it searches the next closest parent controller that is defined as presentation context. In case no one is found, it uses the rootViewController

User Notifications:
Appear on screen are triggered by APN server or Local notifications. Can appear in lock screen, modal presentation (alert), in Notification Center and as a sound

Silent Notifications
From APN server app wakes up in background and can do any processing. Can even get information on the background from a server

New in iOS8

Notification Actions:
Different actions available on the notification: View Accept Maybe Decline Close

With UIMutableUserNotificationAction you respond to the action. If chosen UIUserNotificationActivationModeBackground only seconds are available to execute any code in background

destructive: if it should be shown blue or red

authentication required: if the notification is on the lock screen and the user needs to unlock.

Location Notification:
Notification when entered or exit a region

Define in info.plist NSLocationWhenInUseUsageDescription -> Any text explaining

PDF-JS (Mozilla)
Really good one, generates HTML problem in my case that the information is not structured and I need to be able to parse it and extract information


Really good one, generates HTML problem in my case that the information is not structured and I need to be able to parse it and extract information

Tabular data