轉(zhuǎn) 64-bit Tips

轉(zhuǎn)自 http://blog.sunnyxx.com/2014/12/20/64-bit-tips/

終究還是來了么介。Apple下發(fā)了支持64位的最后通牒:

As we announced in October, beginning February 1, 2015 new iOS apps submitted to the App Store must include 64-bit support and be built with the iOS 8 SDK. Beginning June 1, 2015 app updates will also need to follow the same requirements.

早應(yīng)該做的適配終于要開始動工了,苦了64位的CPU運行了這么久32位的程序碍粥。前段時間公司項目完成了64-bit包的適配囚灼,本沒那么復(fù)雜的事被無數(shù)不標(biāo)準(zhǔn)的老代碼攪和的不輕骆膝,總結(jié)幾個Tip共勉。

Tips

拒絕基本數(shù)據(jù)類型和隱式轉(zhuǎn)換

首當(dāng)其沖的就是基本類型灶体,比如下面4個類型在32-bit和64-bit下分別是多長呢阅签?

1

2

3

4

size_t s1 = sizeof(int);

size_t s2 = sizeof(long);

size_t s3 = sizeof(float);

size_t s4 = sizeof(double);

32-bit下:4, 4, 4, 8;64-bit下:4, 8, 4, 8

(PS: 這個結(jié)果隨編譯器蝎抽,換其他平臺可不一定)

它們的長度變化可能并非我們對64-bit長度加倍的預(yù)期政钟,所以說,程序中出現(xiàn)sizeof的代碼多看兩眼樟结。而且养交,除非你明確知道自己在做什么,應(yīng)該使用下面的類型代替基本類型:

int -> NSInteger

unsigned -> NSUInteger

float -> CGFloat

動畫時間 -> NSTimeInterval

這些都是SDK中定義的類型瓢宦,而我們大部分時間都在跟SDK的API們打交道层坠,使用它們能將類型轉(zhuǎn)換的影響降低很多。

再比如說下面的代碼:

1

2

3

4

NSArray *items = @[@1, @2, @3];

for (int i = -1; i < items.count; i++) {

NSLog(@"%d", i);

}

結(jié)果是刁笙,for循環(huán)一次都沒有進破花。

數(shù)組的count是NSUInteger類型的,-1與其比較時隱式轉(zhuǎn)換成NSUInteger疲吸,變成了一個很大的數(shù)字:

1

2

3

4

(lldb) p i

(int) $0 = -1

(lldb) p (NSUInteger)i

(NSUInteger) $1 = 18446744073709551615

這和64-bit到?jīng)]啥關(guān)系座每,想要說明的是,這種隱式轉(zhuǎn)換也需要小心摘悴,一定要注意和這個變量相關(guān)的所有操作(賦值峭梳、比較、轉(zhuǎn)換)

老式for循環(huán)可以考慮寫成:

1

for (NSUInteger index = 0; index < items.count; index++) {}

當(dāng)然蹂喻,數(shù)組遍歷還是更推薦用for-in或block版本的葱椭,它們之間的比較可以回顧下這篇文章。

使用新版枚舉

和上面的原因差不多口四,枚舉應(yīng)該使用新版的寫法:

1

2

3

4

5

6

typedef NS_ENUM(NSInteger, UIViewAnimationCurve) {

UIViewAnimationCurveEaseInOut,

UIViewAnimationCurveEaseIn,

UIViewAnimationCurveEaseOut,

UIViewAnimationCurveLinear

};

不僅能為枚舉值指定類型孵运,而且當(dāng)賦值賦錯類型時,編譯器還會給出警告蔓彩,沒理由不用這種寫法治笨。

替代Format字符串

適配64-bit時驳概,你是否遇到了下面的惡心寫法:

1

2

NSArray *items = @[@1, @2, @3];

NSLog(@"數(shù)組元素個數(shù):%lu", (unsigned long)items.count);

一般情況下,利用NSNumber的@語法糖就可以解決:

1

2

NSArray *items = @[@1, @2, @3];

NSLog(@"數(shù)組元素個數(shù):%@", @(items.count));

同理旷赖,int轉(zhuǎn)string也可以:

1

2

NSInteger i = 10086;

NSString *string = @(i).stringValue;

當(dāng)然顺又,如需要%.2f這種Format就不適用了。

64-bit下的BOOL

32-bit下等孵,BOOL被定義為signed char稚照,@encode(BOOL)的結(jié)果是'c'

64-bit下,BOOL被定義為bool俯萌,@encode(BOOL)結(jié)果是'B'

更直觀的解釋是:

1

2

3

4

(lldb) p/t (signed char)7

(BOOL) $0 = 0b00000111 (YES)

(lldb) p/t (bool)7

(bool) $1 = 0b00000001 (YES)

32-bit版本的BOOL包括了256個值的可能性锐锣,還會引起一些坑,像這篇文章所說的绳瘟。而64-bit下只有0(NO)雕憔,1(YES)兩種可能,終于給BOOL正了名糖声。

不直接取isa指針

編譯器已經(jīng)默認(rèn)禁用了這種使用斤彼,isa指針在32位下是Class的地址,但在64位下利用bits mask才能取出來真正的地址蘸泻,若真需要琉苇,使用runtime的object_getClass 和object_setClass方法。關(guān)于64位下isa的講解可以看這篇文章

解決第三方lib依賴和lipo命令

以源碼形式出現(xiàn)在工程中的第三方lib悦施,只要把target加上arm64編譯就好了并扇。

惡心的就是直接拖進工程的那些靜態(tài)庫(.a)或者framework,就需要重新找支持64-bit的包了抡诞。這時候就能看出哪些是已無人維護的lib了穷蛹,是時候找個替代品了(比如我全網(wǎng)找不到工程中用到的一個音頻庫的64位包,終于在一個哥們的github上找到昼汗,哭著給了個star- -)

打印Mach-O文件支持的架構(gòu)

如何看一個可執(zhí)行文件是不是支持64-bit呢肴熏?

使用lipo -info命令,比如看看UIKit支持的架構(gòu):

1

2

3

// 當(dāng)前在Xcode Frameworks目錄

sunnyxx$ lipo -info UIKit.framework/UIKit

Architectures in the fat file: UIKit.framework/UIKit are: arm64 armv7s

想看的更詳細(xì)的信息可以使用lipo -detailed_info:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

sunnyxx$ lipo -detailed_info UIKit.framework/UIKit

Fat header in: UIKit.framework/UIKit

fat_magic 0xcafebabe

nfat_arch 2

architecture arm64

cputype CPU_TYPE_ARM64

cpusubtype CPU_SUBTYPE_ARM64_ALL

offset 4096

size 16822272

align 2^12 (4096)

architecture armv7s

cputype CPU_TYPE_ARM

cpusubtype CPU_SUBTYPE_ARM_V7S

offset 16826368

size 14499840

align 2^12 (4096)

當(dāng)然顷窒,還可以使用file命令:

1

2

3

4

sunnyxx$ file UIKit.framework/UIKit

UIKit.framework/UIKit: Mach-O universal binary with 2 architectures

UIKit.framework/UIKit (for architecture arm64):Mach-O 64-bit dynamically linked shared library

UIKit.framework/UIKit (for architecture armv7s):Mach-O dynamically linked shared library arm

上述命令對Mach-O文件適用蛙吏,靜態(tài)庫.a文件,framework中的.a文件鞋吉,自己app的可執(zhí)行文件都可以打印下看看鸦做。

合并多個架構(gòu)的包

如果,我們有MyLib-32.a和MyLib-64.a谓着,可以使用lipo -create命令合并:

1

sunnyxx$ lipo -create MyLib-32.a MyLib-64.a -output MyLib.a

支持64-bit后程序包會變大么泼诱?

會,支持64-bit后漆魔,多了一個arm64架構(gòu)坷檩,理論上每個架構(gòu)一套指令,但相比原來會大多少還不好說改抡,我們這里增加了大概50%矢炼,還有聽說會增加一倍的。

一個lib包含了很多的架構(gòu)阿纤,會打到最后的包里么句灌?

不會,如果lib中有armv7, armv7s, arm64, i386架構(gòu)欠拾,而target architecture選擇了armv7s, arm64胰锌,那么只會從lib中l(wèi)ink指定的這兩個架構(gòu)的二進制代碼,其他架構(gòu)下的代碼不會link到最終可執(zhí)行文件中藐窄;反過來资昧,一個lib需要在模擬器環(huán)境中正常link,也得包含i386架構(gòu)的指令荆忍。

Checklist

最后列一下官方文檔中的注意點:

不要將指針強轉(zhuǎn)成整數(shù)

程序各處使用統(tǒng)一的數(shù)據(jù)類型

對不同類型的整數(shù)做運算時一定要注意

需要定長變量時格带,使用如int32_t, int64_t這種定長類型

使用malloc時,不要寫死size

使用能同時適配兩個架構(gòu)的格式化字符串

注意函數(shù)和函數(shù)指針(類型轉(zhuǎn)換和可變參數(shù))

不要直接訪問Objective-C的指針(isa)

使用內(nèi)建的同步原語(Primitives)

不要硬編碼虛存頁大小

Go Position Independent

References

https://developer.apple.com/library/prerelease/ios/documentation/General/Conceptual/CocoaTouch64BitGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40013501-CH1-SW1

http://www.sealiesoftware.com/blog/archive/2013/09/24/objc_explain_Non-pointer_isa.html

http://www.bignerdranch.com/blog/64-bit-smorgasbord/

http://www.bignerdranch.com/blog/bools-sharp-corners/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末刹枉,一起剝皮案震驚了整個濱河市叽唱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌微宝,老刑警劉巖棺亭,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蟋软,居然都是意外死亡镶摘,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門岳守,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钉稍,“玉大人,你說我怎么就攤上這事棺耍」蔽矗” “怎么了?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵蒙袍,是天一觀的道長俊卤。 經(jīng)常有香客問我,道長害幅,這世上最難降的妖魔是什么消恍? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮以现,結(jié)果婚禮上狠怨,老公的妹妹穿的比我還像新娘约啊。我一直安慰自己,他們只是感情好佣赖,可當(dāng)我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布恰矩。 她就那樣靜靜地躺著,像睡著了一般憎蛤。 火紅的嫁衣襯著肌膚如雪外傅。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天俩檬,我揣著相機與錄音萎胰,去河邊找鬼。 笑死棚辽,一個胖子當(dāng)著我的面吹牛技竟,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播屈藐,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼灵奖,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了估盘?” 一聲冷哼從身側(cè)響起瓷患,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎遣妥,沒想到半個月后擅编,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡箫踩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年爱态,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片境钟。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡锦担,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出慨削,到底是詐尸還是另有隱情洞渔,我是刑警寧澤,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布缚态,位于F島的核電站磁椒,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏玫芦。R本人自食惡果不足惜浆熔,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望桥帆。 院中可真熱鬧医增,春花似錦慎皱、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至邓萨,卻和暖如春地梨,著一層夾襖步出監(jiān)牢的瞬間菊卷,已是汗流浹背缔恳。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留洁闰,地道東北人歉甚。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像扑眉,于是被迫代替她去往敵國和親纸泄。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內(nèi)容