本篇是根据《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
在Architechtures中设置Architectures和Valid Architectures两个项目
- 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的数据类型参照表: