Monday, January 13, 2014

Migrate code to support 64-bit in iOS7

As Apple requires all app submissions to use XCode5 with iOS7 SDK after February 1st, 2014, it becomes important to make sure that your codebase is compatible with iOS7 SDK, especially the 64-bit support since the primitive types change from 32 to 64 bits.

This means that NSInteger/NSUInteger are long instead of int.  CGFloat is double, not float.

There are many possible compiler warnings and here are the resolutions.

Case 1: Implicit conversion loses integer precision: 'long' to 'int'

Example:

    NSInteger row = ...;

    int rowWithLineCount = (rows - 1) / 5// compiler warning

Solution:
    NSInteger rowWithLineCount = (rows - 1) / 5 ;

Note: Use NSUInteger if the right hand expression is evaluated to unsigned integer.

Case 2: Implicit conversion loses integer precision: 'NSInteger' (aka 'long') to SomeEnum'

Example:

  typedef enum {
    ...
  } SomeEnum;

  NSInteger someValue;
  SomeEnum somefield = someValue; // compiler warning

Solution: Use NS_ENUM

  typedef NS_ENUM(NSInteger, SomeEnum) {
    ...
  };

Case 3: Implicit conversion loses integer precision: 'SomeEnum' (aka 'enum SomeEnum') to int'

Example:

  typedef NS_OPTIONS(NSUInteger, SomeEnum) {
    ...
  }
  SomeEnum somefield;

  NSNumber *number = [NSNumber numberWithInt:self.someField]; // compiler warning

Solution:

  NSNumber *number = [NSNumber numberWithLong:self.someField];

Case 4: Values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead

Example:

NSInteger statusCode = ...;

NSLog(@"Failed response code:%d", statusCode); // compiler warning

Solution:

NSLog(@"Failed response code:%ld", (long)statusCode);

Note: This applies to %lu string pattern and (unsigned long) casting for NSUInteger as well.

Case 5: Replace abs((NSInteger)value) with labs()