升級(jí)了Xcode8以后具滴,發(fā)生了很多很奇怪的事情蚂维,譬如說(shuō)注釋快捷鍵失效的問(wèn)題,然鵝我們的項(xiàng)目遇到了更加神奇的問(wèn)題力图,是跟UIDatePicker這個(gè)系統(tǒng)控件相關(guān)。
先上代碼
UIDatePicker *datePicker = [[UIDatePicker alloc] init];
//設(shè)置本地語(yǔ)言
datePicker.locale = [NSLocale localeWithLocaleIdentifier:@"zh"];
//設(shè)置日期顯示的格式
NSDate *curDate = [NSDate date];
[datePicker setDate:curDate animated:NO];
datePicker.datePickerMode = UIDatePickerModeDate;
//設(shè)置accountTextField的inputView控件為datePicker
self.accountTextField.inputView = datePicker;
一段很簡(jiǎn)單很普通的代碼掺逼,就莫名奇妙地crash了吃媒,堆棧如下
什么鬼,設(shè)置locale也會(huì)錯(cuò)坪圾?那不設(shè)置了行不行捏晓折?也不行!
從上圖會(huì)看到一個(gè)很奇怪的堆棧兽泄,似乎是UIDatePicker在設(shè)置amString的時(shí)候有什么東東有問(wèn)題才導(dǎo)致的crash漓概,而且命令行也有一個(gè)error輸出:
-[__NSCFConstantString name]: unrecognized selector sent to instance 0x109bd8900
上google搜索了一通,并沒有人說(shuō)到這個(gè)問(wèn)題病梢,而且更讓人崩潰的是胃珍,自己新建一個(gè)demo工程跑代碼完全沒問(wèn)題,一用到我們的工程上面就不行了蜓陌∶僬茫考慮了一下,說(shuō)不定是build setting有問(wèn)題或者引入了奇怪的第三方庫(kù)钮热,嘗試了1個(gè)多小時(shí)填抬,放棄了,感覺這個(gè)方向工作量太大隧期,而且也應(yīng)該不是直接原因飒责。這個(gè)時(shí)候靜下心來(lái)赘娄,再分析一下crash堆棧,還是看出一點(diǎn)線索了
留意一下箭頭方向的那一坨匯編宏蛉,是這樣子的
0x10ae74dc6 <+346>: leaq 0x2e7263(%rip), %rdx ; @"timeZone"
0x10ae74dcd <+353>: movq %rbx, %rsi
0x10ae74dd0 <+356>: callq *0x2c49ca(%rip) ; (void *)0x000000010e7bfac0: objc_msgSend
0x10ae74dd6 <+362>: testq %rax, %rax
0x10ae74dd9 <+365>: je 0x10ae74df1 ; <+389>
0x10ae74ddb <+367>: movq (%r12,%r14), %rdi
0x10ae74ddf <+371>: movq 0x2c4782(%rip), %rcx ; (void *)0x000000010efd71d0: kCFDateFormatterTimeZone
0x10ae74de6 <+378>: movq (%rcx), %rsi
0x10ae74de9 <+381>: movq %rax, %rdx
0x10ae74dec <+384>: callq 0x10b0aedc6 ; symbol stub for: CFDateFormatterSetProperty
0x10ae74df1 <+389>: movq (%r12,%r15), %rdi
這段代碼的意思估計(jì)大家也大致看得懂遣臼,首先初始化timeZone這個(gè)字符串,然后調(diào)用函數(shù)拾并,再設(shè)置屬性揍堰,所以就猜測(cè),是不是要先初始化UIDatePicker的timeZone才行嗅义。
修正后的代碼如下屏歹,跑通了。我覺得這個(gè)問(wèn)題可能我還是沒找到最終的根源芥喇,但是給我?guī)?lái)了另外一個(gè)解決問(wèn)題的思路西采,就是仔細(xì)考慮一下crash堆棧的匯編相關(guān)代碼凰萨,說(shuō)不定就能找到一些特別的解決思路了继控。
UIDatePicker *datePicker = [[UIDatePicker alloc] init];
//跟隨系統(tǒng)時(shí)區(qū)
datePicker.timeZone = [NSTimeZone systemTimeZone];//一定要先設(shè)置這個(gè),不然會(huì)crash
//設(shè)置本地語(yǔ)言
datePicker.locale = [NSLocale localeWithLocaleIdentifier:@"zh"];
//設(shè)置日期顯示的格式
NSDate *curDate = [NSDate date];
[datePicker setDate:curDate animated:NO];
datePicker.datePickerMode = UIDatePickerModeDate;
//設(shè)置accountTextField的inputView控件為datePicker
self.accountTextField.inputView = datePicker;
奇怪的是胖眷,這個(gè)屬性本身系統(tǒng)就已經(jīng)設(shè)置為nil了武通,這種必須要顯式設(shè)置才能好的邏輯真的不知道是哪里影響了。
更為奇怪的是珊搀,NSTimeZone的systemTimeZone方法冶忱,提示是IOS10以后的方法,WTF境析?囚枪!誰(shuí)能解釋一下這個(gè)瘋狂的IOS?劳淆!