At the Worldwide Developers Conference 2017, Apple urged all the developers to move their applications to 64-bit apps. iOS 11 has dropped the support for 32-bit apps. Any 32-bit application will refuse to get launched and show an alert for forcing the developers to release its 64-bit update. As Apple has already started to remove those apps from the App Store which have not been updated to its newer paradigm, it is necessary for the developers to convert their 32-bit apps to 64-bit.

Update Bit Mobisoft Infotech

Here we have clearly defined the difference between 32-bit and 64-bit iOS apps and the ways to upgrade your older apps as per the Apple paradigm.

32-bit vs 64-bit

64 Bit Processor Over 32 Bit Mobisoft Infotech
Apple has introduced A7 processor in 2013 in iPhone 5S which is a 64-bit processor.

Let’s compare the advantages of the 64-bit processor over 32-bit.

1. Memory Addressing: A 32-bit processor can only make use of RAM of up to 4 GB. In other words a 32-bit processor can store memory addresses of up to 4 GB (2^32). A 64-bit processor can store memory addresses of up to 16 billion GB. 64-bit processors are fast but ideally, 4GB of RAM is more than sufficient to play games and perform other tasks in a smartphone. Apple hasn’t even released an iPhone which has
RAM > 3 GB.

2. Calculation Speed: A 64-bit processor can perform 64-bit integer operations just as quickly as 32-bit integer operations, but a 32-bit processor performs 64-bit calculations much more slowly.

3. Operating system and App supports: OS and App should support 64-bit architecture to take advantages of 64-bit processor. Apple is supporting 64-bit architecture from iOS 7 onwards.

Apart from above 3 points shift to 64-bit processors gives CPU more memory bandwidth, more efficient instruction set with more registers. which makes 64-bit device significantly faster.

To take advantages of 64-bit processor your app should be built to support 64-bit runtime. Till iOS 10 Apple was giving support to 32-bit runtime, but from iOS 11 Apple has announced that it will remove support for 32-bit that means all the app which are built for 32-bit will stop working on iOS 11.

Followings are the point to check while converting the 32-bit app to 64-bit.

  • Open the app project in latest Xcode (version >= 8)
  • Update project settings to support the iOS version 5.1.1 or later because 64-bit architecture is not supported on version earlier than the iOS 5.1.1
  • In a Build Settings section of your project settings, set the Standard architectures (arm64) for Architectures
  • Test your project on the 64-bit devices
  • Take benefits of instruments to check the application’s memory usage
  • Submit app for approval

The above changes would raise some compiler errors and warnings in your project. In this article, we have covered up how to update the code to support a 64-bit runtime environment.

Below are those problems which frequently occur while porting the app to a 64-bit runtime environment.

Pointers to Integer Casting

Don’t cast the pointer to an integer, if you do so you have to be sure that all variables which you created would be long enough to store the address value. If you have to convert the pointer to an integer type, use the uintptr_t type to avoid truncation. You want to convert a pointer to the int because you have to perform the arithmetic on an address. In a 32-bits runtime, this code runs successfully because a pointer and an int type are of the same sizes whereas in 64-bit runtime the pointer is larger than the int type, that’s why the assignment loses some of the pointer’s data.

int *pointer = some value;
int *pointer_2 = (int*)((int) pointer + 1); // incorrect
Int *pointer_2 = pointer + 1; // correct  (by increment the pointer, pointer is being advanced by its native size)

Use Data Types Repeatedly

Several common programming errors encountered when you ignore the use of data types while coding. Even when the compiler warns you about the problems, always match those variable which receives the results to a function’s return type.

For example:

A) Value truncation happens if you assign int variable to a function which returns long value.

long getItemsCount;             
     int a =  getItemsCount; // incorrect
     long a =  getItemsCount; // correct

When the return type is larger integer than a receiving variable, the values get truncated. In a 32-bits runtime, both long and int are 32-bits, that’s why the assignment to the int type works. In a 64-bit runtime, upper 32-bits of your result get lost when such assignment is made.

B) Passing input parameter: Value truncation happens when you pass a long to the function which expects an int.

-addValue:(int i);

C) Returning value: Value truncation happens when you return the long in place of int.

int getItemsCount {
              return LONG_MAX
}

You should also check for following integer types and its correct usage:

  • long
  • size_t
  • CFIndex
  • NSInteger

fpos_t and off_t types: In both runtime environments, they are 64-bits in size, hence never assign both of them to the int type. By default, if you update your project then a -Wshorten-64-to-32 option gets automatically enabled, hence the compiler will automatically warn you about those cases where the value is truncated.

Enumerations Typed

Enumerated types may have a size which is larger than the one you expected. So assign the enumerated values to the variable with a proper data type.

Integer Computation

In addition to the truncation problems, it is also necessary to take care of integer computations, for instance when working with the sign integers.

For Example:

int x = -3;
unsigned int y = 2;
long c = x + y;

The resultant value is -1 in the 32-bit runtimes (0xffffffff). On the other hand, when you will run this code in a 64-bit runtime, a result would be 4294967296 (0x00000000ffffffff). The solution to this problem is to declare y as the long variable.

In Cocoa Touch: General Type-Conversion Problems:

NSInteger changes the size in a 64-bits code. The NSInteger is the 64-bit integer in a 64-bit runtime and the 32-bit integer in a 32-bit runtime. So while receiving information from the framework method which takes an NSInteger, use the NSInteger to hold the value.

Following are some errors which can arise when assuming

  • NSInteger as int in 64-bit runtime.
  • When converting from or to an NSNumber object
  • When decoding and encoding data using an NSCoder class
  • When accessing constants which are defined in a framework as NSInteger.
  • CGFloat changes the size in the 64-bit code. Hence use the CGfloat consistently.

Performing Integer Calculations:

The sign extension rules to treat a top bit in the integer as the sign bit for a variable with larger width:

  1. Unsigned values are zero extended when upgraded to the larger type.
  2. Signed values are sign extended always when promoted to the larger type, even when their resulting type is an unsigned one.
  3. Decimal numbers are treated as the signed types.
  4. Constants are considered as the smallest size which would hold the value.
  5. The sum of an unsigned value and a signed value of the same size is the unsigned value.
  6. Numbers which is written in the hexadecimal might be treated as long, long long, and int types and can be either unsigned or signed types by the compiler.

For Example:

int X=-2;
unsigned int Y=1;
long Z = X + Y;
long long total =Z; // to get the consistent size for the printing.
printf("%lld\n", total);

When the code will be executed in a 32-bit runtime, a result would be -1 (0xffffffff).
When that same code will be executed in a 64-bit runtime, a result would be 4294967295 (0x00000000ffffffff) which would be incorrect.
This was due to rule number 5 and 1. To fix this issue, cast Y to a long integer.

Bits and Bit Masks:

Never assume that any data type has the particular length: For shifting bits on a variable of the type long integer, you have to use LONG_BIT to determine the bits in the variable. This is because the result of the shift which surpass the length of the variable is architecture dependent.

You should use the inverted masks if needed: long integers width always differs between the 64-bit and 32-bit runtimes. If you want a mask value to contain the ones in upper 32-bits in a 64-bits runtime, write the mask as a bitwise inverse of that value’s inverse. And use the fixed-width mask when you want a mask value to contain the zeros in the upper bits.

Memory Allocation:

Never use the malloc(size) to allocate the space for your variable. Instead, you can use sizeof to get the size of the variable you want to allocate.

Data Structures:

You have to create a data structures with memory alignment and fixed size. It means that maybe these data structures have the same representation in 64-bit and 32-bit runtimes to avoid the problems when users will store data in the 32-bit devices and retrieve them from the 64-bit devices.

String format:

While printing the variable with a printf function, you should always use a correct format string:

%d for int
%zu for size_t,
%lld for long long,
%ld for long,
%p for pointers.
%td for ptrdiff_t

Functions Pointers and Function:

The difference between function pointers and function is that function calls along with variadic prototypes apply the different sequence of instructions for reading their parameters while function takes a fixed list of the parameters.

int fixedFunction(long a, long b, long c);
int variadicFunction(int a,...);
 
int main
{
      int value2 = fixedFunction(10,20,30);
int value1 = variadicFunction(10,20,30,40);
}

The first function (fixed Function) takes long integers and input parameter. The next function takes the variable number of parameters. In a 32-bits runtime, both of these function calls use similar sequence of the instructions for reading the parameter data. In a 64-bit runtime, these functions are compiled using the conventions. So you have to be sure that the function is always called correctly with correct data types.

Define Function Prototypes:

The compiler will generate errors if you try to make the function call to that function which does not have the explicit prototype with modernized project settings. Function prototype helps compiler to determine whether that function is the variadic function or not.

Accessing Objective-C Pointer Directly

Do not directly access an object’s isa field, this code fails in 64-bit runtime. To read an object’s isa field, use the class property or call the object_getClass function. To write to an object’s isa field, call the object_setClass.

64 Bit Processor Mobisoft Infotech

Wrapping Up!!

As Apple has made it very clear at WWDC 2017, the future of iOS app development is 64 bit only. Even if you have not updated your application on the App Store for supporting the 64-bit environment, we recommend you to submit an update soon so your users will continue to use the application on iOS 11, which would be in the hands of millions of Apple customers this fall.

Need help with converting your 32-bit iOS apps into the 64-bit apps to support iOS 11 and re-submit your iOS app with latest configuration on the Apple App Store? Check out our iOS app development services to know more.

Author’s Bio

mobisoft-pritam
Pritam Barhate

Pritam Barhate, with an experience of 10+ years in technology, heads Technology Innovation at Mobisoft Infotech. He has a rich experience in design and has been a consultant for a variety of industries and startups. At Mobisoft Infotech, he primarily focuses on technology resources and develops the most advanced solutions. Follow him @pritambarhate