本篇是根据《64-Bit Transition Guide for Cocoa Touch》进行编写。

前言

Apple在去年10月份公布,2015年2月1号后提交到App store上的App必须支持64bit。iphone 5s中的A7 cpu是第一个支持64bit的ARM架构

支持64bit的基本条件如下:

  • xcode版本必须是5.1.1以上.
  • 如果要同时支持32bit和64bit,则deloyment target最小为5.1.1
  • 64bit的程序只能运行在64的cpu架构上(iphpne5s之后的设备),并且操作系统至少都是7.0以上

设置64bit编译环境

我当前的xcode版本是6.0.1,因为本次我做的app不支持ios7.0以下的设备,所以将iOS Deplloyment Target设置为iOS7.0

iOS 代码转汇编 转移到ios代码位数_OC

Architechtures中设置ArchitecturesValid Architectures两个项目

iOS 代码转汇编 转移到ios代码位数_iOS开发_02

  • Architectures
    这个选项是选择,你想要该App支持的的指令集,常见的有armv7,armv7s和arm64等。
  • Valid Architectures
    这个选项是你将要编译的指令集有哪些,真正编译出来的指令集版本是该选项和上一个选项的交集。

上图中还有一个选项是Build Active Architecture Only,如果设置为YES,则如果模拟器选择的是iphone6,就编译支持iphone6指令集的二进制代码,如果选择为NO,则会按照Architectures和Valid Architectures两个选项的交集生成多个版本指令集的二进制代码。

各个指令集所支持的谁被如下:

ARMv8/ARM64: iPhone 6(Plus), iPhone 5s, iPad Air(2), Retina iPad Mini(2,3)
ARMv7s: iPhone 5, iPhone 5c, iPad 4 
ARMv7: iPhone 3GS, iPhone 4, iPhone 4S, iPod 3G/4G/5G,     iPad, iPad 2, iPad 3, iPad Mini   
ARMv6: iPhone, iPhone 3G, iPod 1G/2G

如果要支持64bit的架构,必须要将arm64指令集包括在内。

切换成64bit所带来的影响

主要影响有以下几个方面:

  • 数据类型的变换
    某些OC的数据类型在32bit和64bit下所占用的内存不一样,支持的精度也不一样
  • 函数调用的改变
    主要是指函数中的参数传递问题,因为参数可能在不同的bit架构下精度发生变换,在底层的调用过程就可能发生变换。这种情况比较少见,如果你的代码中有汇编语句,要注意不同架构下汇编语句需要做出调整。
  • OC的变化
    在64bit下,不能直接访问isa指针,需要调用runtime函数来访问isa指针信息。
  • 其他
    汇编语句的修改,ABI描述的改变等。

修改代码兼容64bit

设置64bit环境之后,编译一下,可能会产生很多warning和error,error的产生原因有多种,某些第三方的静态库可能也不支持64bit。

常见的warning就是数据类型转换所造成的,因为某些OC数据类型在32bit和64bit下的定义有所不同,例如NSInteger和NSUInteger,定义如下:

#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
 typedef long NSInteger;
 typedef unsigned long NSUInteger;
 #else
 typedef int NSInteger;
 typedef unsigned int NSUInteger;
 #endif



在64bit下NSInteger被定义成long类型,在32bit下被定义成int类型。

有一个修改数据转换的小tips:

#修改前
 -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{

return [NSString stringWithFormat:@"第%d年",section+1];
 }

#修改后
 -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{

return [NSString stringWithFormat:@"第%@年",@(section+1)];
}



[NSString stringWithFormat:@"第%d年",section+1];该语句中,不管是将类型设置成%d还是%ld都会报warning,因为这两种方法都只能兼容一种bit架构的指令集,所以这里将其转换成NSNumber类型,然后用%@的方式,就能避免warning。

因为32bit和64bit平台的数据类型在内存中所占的长度不一样,所以要主要转换和计算时数据被截取等问题。下面是32bit和64bit的数据类型参照表:

iOS 代码转汇编 转移到ios代码位数_iOS 代码转汇编_03

更加详细的内容参见 < 64-Bit Transition Guide for Cocoa Touch >