UIWebSelectSinglePicker的crash問題

  • 復(fù)現(xiàn)步驟:

用UIWebView打開這個測試網(wǎng)頁,將其中<select></select>節(jié)點中所有的option節(jié)點刪除褐奴,會出現(xiàn)一個空白的UIPickerView按脚,如下圖:

IMG_0630.PNG

在這個空白的picker中隨便劃幾下再點完成按鈕便會crash。

  • 崩潰堆棧:
Date/Time:       2017-06-16 18:15:02.000 +0800
OS Version:      iOS 10.2 (14C92)
Report Version:  104
 
Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x00000000 at 0x0000000000000000
Crashed Thread:  0
 
Application Specific Information:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'
 
Thread 0 name:  Dispatch queue: com.apple.main-thread
 
Thread 0 Crashed:
0   CoreFoundation                  __exceptionPreprocess + 124
1   libobjc.A.dylib                 objc_exception_throw + 56
2   CoreFoundation                  -[__NSArrayM removeObjectAtIndex:] + 0
3   UIKit                           -[UIWebSelectSinglePicker pickerView:didSelectRow:inComponent:] + 72
4   UIKit                           -[UIPickerView _sendSelectionChangedForComponent:notify:] + 116
5   UIKit                           -[UIPickerView _sendSelectionChangedFromTable:notify:] + 344
6   UIKit                           -[UIPickerTableView _scrollingFinished] + 188
7   UIKit                           -[UIPickerTableView scrollViewDidEndDecelerating:] + 28
8   UIKit                           -[UIScrollView(UIScrollViewInternal) _scrollViewDidEndDeceleratingForDelegate] + 132
9   UIKit                           -[UIScrollView(UIScrollViewInternal) _stopScrollDecelerationNotify:] + 332
10  UIKit                           -[UIScrollView _smoothScrollWithUpdateTime:] + 2356
11  QuartzCore                      CA::Display::DisplayLinkItem::dispatch(unsigned long long) + 44
12  QuartzCore                      CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) + 444
13  IOKit                           IODispatchCalloutFromCFMessage + 372
14  CoreFoundation                  __CFMachPortPerform + 180
15  CoreFoundation                  __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 56
16  CoreFoundation                  __CFRunLoopDoSource1 + 436
17  CoreFoundation                  __CFRunLoopRun + 1840
18  CoreFoundation                  CFRunLoopRunSpecific + 444
19  GraphicsServices                GSEventRunModal + 180
20  UIKit                           -[UIApplication _run] + 684
21  UIKit                           UIApplicationMain + 208
22  moma                            main (main.m:15)
23  libdyld.dylib                   start + 4
  • crash分析:

  • 首先看看-[UIWebSelectSinglePicker pickerView:didSelectRow:inComponent:]方法中具體發(fā)生崩潰的邏輯:

    1527236825624-image.png

圖中在對optionItems數(shù)組進(jìn)行objectAtIndex時直接將方法第二個參數(shù)r15傳了進(jìn)去敦冬,而此時optionItems是個空數(shù)組辅搬,所以發(fā)生了崩潰。

  • 解決方法:

按照上面的分析如果我們?nèi)ook-[UIWebSelectSinglePicker pickerView:didSelectRow:inComponent:]方法似乎不太靠譜脖旱,這個方法太長堪遂,我們繼續(xù)往上找在哪里調(diào)用了該方法:

void -[UIPickerView _sendSelectionChangedForComponent:notify:](void * self, void * _cmd, long long arg2, bool arg3) {
    rcx = arg3;
    r14 = arg2;
    rbx = self;
    if ((rbx->_pickerViewFlags & 0x8) != 0x0) {
            rcx = rcx ^ 0x1;
            if (rcx == 0x0) {
                    rax = [rbx selectedRowInComponent:r14];
                    [rbx->_delegate pickerView:rbx didSelectRow:rax inComponent:r14];
            }
    }
    rdi = rbx;
    rdx = r14;
    [rdi _noteScrollingFinishedForComponent:rdx];
    return;
}

看到這里思路就清晰了,原來崩潰的UIWebSelectSinglePickerUIPickerViewdelegate萌庆,那我們就行調(diào)用delegate的地方入手進(jìn)行防護(hù)溶褪。

  • Code

代碼很簡單,直接貼在這里踊兜。

#import <objc/runtime.h>

@implementation UIPickerView (DEFWebSinglePickCrash)

+ (void)load
{
    
    SEL originalSelector = @selector(_sendSelectionChangedForComponent:notify:);
    
    SEL overrideSelector = @selector(swizzle_sendSelectionChangedForComponent:notify:);
    Method originalMethod = class_getInstanceMethod(self, originalSelector);
    Method overrideMethod = class_getInstanceMethod(self, overrideSelector);
    
    BOOL success = class_addMethod(self, originalSelector, method_getImplementation(overrideMethod), method_getTypeEncoding(overrideMethod));
    if (success) {
        class_replaceMethod(self, overrideSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, overrideMethod);
    }
}

- (void)swizzle_sendSelectionChangedForComponent:(int)arg1 notify:(BOOL)arg2
{
    Class class = NSClassFromString(@"UIWebSelectSinglePicker");
    if ([self isKindOfClass:class]) {
        NSArray *optionItems = [self valueForKey:@"_optionItems"];
        if (optionItems.count > 0) {
            [self swizzle_sendSelectionChangedForComponent:arg1 notify:arg2];
        }
    } else {
        [self swizzle_sendSelectionChangedForComponent:arg1 notify:arg2];
    }
}

@end

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末竿滨,一起剝皮案震驚了整個濱河市佳恬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌于游,老刑警劉巖毁葱,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異贰剥,居然都是意外死亡倾剿,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進(jìn)店門蚌成,熙熙樓的掌柜王于貴愁眉苦臉地迎上來前痘,“玉大人,你說我怎么就攤上這事担忧∏鄣蓿” “怎么了?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵瓶盛,是天一觀的道長最欠。 經(jīng)常有香客問我,道長惩猫,這世上最難降的妖魔是什么芝硬? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮轧房,結(jié)果婚禮上拌阴,老公的妹妹穿的比我還像新娘。我一直安慰自己奶镶,他們只是感情好迟赃,可當(dāng)我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著实辑,像睡著了一般捺氢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上剪撬,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天摄乒,我揣著相機與錄音,去河邊找鬼残黑。 笑死馍佑,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的梨水。 我是一名探鬼主播拭荤,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼疫诽!你這毒婦竟也來了舅世?” 一聲冷哼從身側(cè)響起旦委,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎雏亚,沒想到半個月后缨硝,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡罢低,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年查辩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片网持。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡宜岛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出功舀,到底是詐尸還是另有隱情萍倡,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布辟汰,位于F島的核電站遣铝,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏莉擒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一瘫絮、第九天 我趴在偏房一處隱蔽的房頂上張望涨冀。 院中可真熱鬧,春花似錦麦萤、人聲如沸鹿鳖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽翅帜。三九已至,卻和暖如春命满,著一層夾襖步出監(jiān)牢的瞬間涝滴,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工胶台, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留歼疮,地道東北人。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓诈唬,卻偏偏與公主長得像韩脏,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子铸磅,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,876評論 2 361

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