iOS KeyBoard Extention 記錄

鍵盤開發(fā)其實遇到了很多坑郁油,之前未記錄下來本股,想起來哪些記錄哪些吧...

1. 鍵盤高度調(diào)整不生效

鍵盤高度的調(diào)整必須通過約束控制,但是在viewDidload中設(shè)置約束桐腌,并不能生效拄显,最終高度還是系統(tǒng)設(shè)置的高度(可以看到是系統(tǒng)后添加了高度約束并生效)
思路就是在系統(tǒng)設(shè)置約束后再添加自定義的高度約束,前后嘗試了很多方案

  • 方案1:在viewDIdAppear中設(shè)置高度約束案站,但其實時機有些晚
  • 方案2:重寫UIInputView子類的-setFrame方法躬审,當(dāng)判斷frame高度>0并且≠想設(shè)置的高度時,重新設(shè)置高度約束蟆盐,這個方案用了一段時間承边,沒發(fā)現(xiàn)什么問題
  • 方案3:重寫- (void)updateViewConstraints方法,進(jìn)行約束判斷修改
- (void)updateViewConstraints{
 
    [self updateKeyBoardHeight];

    [super updateViewConstraints];
}
- (void)updateKeyBoardHeight{
    CGFloat newHeight = 500; // 這里高度根據(jù)業(yè)務(wù)計算
    if (self.heightConstraint.constant == newHeight) {
        return;
    }
    if (self.heightConstraint) {
        self.heightConstraint.constant = newHeight;
        return;
    }
    self.heightConstraint = [NSLayoutConstraint constraintWithItem: self.view
                                                         attribute: NSLayoutAttributeHeight
                                                         relatedBy: NSLayoutRelationEqual
                                                            toItem: nil
                                                         attribute: NSLayoutAttributeNotAnAttribute
                                                        multiplier: 0.0
                                                          constant: newHeight];
    
    self.heightConstraint.priority = UILayoutPriorityDefaultHigh;
    [self.view addConstraint:self.heightConstraint];
}
2. 鍵盤邊緣按鈕點擊- touchBegin...調(diào)用慢

由于我們鍵盤按鈕點擊是通過重寫 touchs系列方法 分發(fā)事件的石挂,發(fā)現(xiàn)靠近屏幕邊緣的按鈕博助,點擊高亮效果較難觸發(fā),當(dāng)時看了搜狗輸入法也是有同樣的問題痹愚,就沒有研究原因富岳,歸結(jié)系統(tǒng)bug了....
很久之后發(fā)現(xiàn)百度輸入法是正常的,便又研究了一番拯腮,發(fā)現(xiàn)點擊邊緣按鈕時窖式,- touchBegin- touchEnd的時間間隔極短,其它區(qū)域按鈕就是正常的动壤,猜測是視圖層級中存在Gesture手勢 延遲了- touchBegin 或者 未延遲 - touchEnd(因為手勢有兩個屬性 delaysTouchesEndeddelaysTouchesBegan
通過遍歷視圖發(fā)現(xiàn)

[9744:673157] <_UIHostedWindow: 0x105f096b0; frame = (0 0; 390 280); gestureRecognizers = <NSArray: 0x281e79380>; layer = <UIWindowLayer: 0x281043920>>
[9744:673157] <_UISystemGestureGateGestureRecognizer: 0x105f0b240; state = Possible; delaysTouchesBegan = YES; view = <_UIHostedWindow 0x105f096b0>>

果然_UIHostedWindow上存在一個手勢的 delaysTouchesBegan = YES;

// 方案就是: 
// 修改這個手勢的 delaysTouchesBegan = NO;
// 我把代碼放在了這里
- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    dispatch_async(dispatch_get_main_queue(), ^{
        // 這是為了解決 鍵盤邊緣點擊時 touchBegin和touchEnd的間隔極端 導(dǎo)致點擊高亮效果無法顯示
        // 這個修改會導(dǎo)致一個控制臺警告 也沒發(fā)現(xiàn)啥影響  暫時就不管了
        // [Warning] Trying to set delaysTouchesBegan to NO on a system gate gesture recognizer - this is unsupported and will have undesired side effects
        for (UIGestureRecognizer *ges in self.view.window.gestureRecognizers) {
            if (ges.delaysTouchesBegan) {
                ges.delaysTouchesBegan = NO;
                // ges.delaysTouchesEnded = YES;
            }
        }
    });
}
3. 鍵盤內(nèi)存限制66M

這個其實沒啥說的萝喘,代碼上及時釋放就行了,特別是圖片加載上尤其要注意

4. 鍵盤實例 UIInputViewController實例獲取 (巨坑)

不知道其他家是怎么獲取的狼电,我們早期在 Controller的 - init中 用一個全局指針記錄下當(dāng)前鍵盤實例蜒灰, 在其他業(yè)務(wù)中都是通過這個指針獲取當(dāng)前實例進(jìn)行業(yè)務(wù)處理,這也埋下了一個很深的隱患肩碟,這個bug足足有一年多未解決..
在某種情況下强窖,系統(tǒng)會創(chuàng)建多個UIInputViewController實例,而當(dāng)前顯示的卻可能是不是最后一次創(chuàng)建的實例削祈,就導(dǎo)致代碼中所有獲取鍵盤實例的地方都錯誤的獲取了最后一次創(chuàng)建的鍵盤實例翅溺,從而導(dǎo)致無法輸入上屏/UI更新失敗等一系列問題。
在調(diào)查中髓抑,我們早期走錯了方向咙崎,一直沒想過會同時出現(xiàn)多個鍵盤實例,再加上很難復(fù)現(xiàn)吨拍,竟然一直沒發(fā)現(xiàn)是我們代碼上取錯了實例對象...
這個解決方案其實很簡單:不要通過全局指針方式獲取最后一次init的鍵盤實例褪猛,在創(chuàng)建子業(yè)務(wù)實例時,在各自的基類中弱引用當(dāng)前鍵盤實例即可羹饰,或者一層一層向上弱引用也可以伊滋。

5. 鍵盤實例 UIInputViewController 生命周期函數(shù)調(diào)用多次

多次實驗發(fā)現(xiàn)UIInputViewController實例碳却,并不是每次彈出鍵盤都重新實例化,系統(tǒng)會在一些場景復(fù)用之前創(chuàng)建的鍵盤實例笑旺,即 init viewDidLoad 執(zhí)行一次昼浦,但 willAppear/DidAppear/willDisappear/DidDisappear 會調(diào)用多次,需要注意防止一些寫在生命周期方法中的初始化代碼執(zhí)行多次筒主。(-viewWillDisappear 這個方法特殊关噪,正常收起鍵盤,貌似就會調(diào)用兩次乌妙, 尚不知道原因...)

6. 鍵盤View中多點觸控失效(這個問題也比較坑使兔,宿主APP的部分設(shè)置會影響到鍵盤)

我們鍵盤中的按鈕點擊事件是通過-touchBegin...系列方法處理的,一個按鈕按下狀態(tài)冠胯,是允許點擊第二個按鈕的火诸,這套方案也一直未出現(xiàn)過問題锦针。
一天用戶反饋了視頻荠察,演示了第一個按鈕不抬起,第二個按鈕無法按下的情況奈搜;查了很長時間始終不能復(fù)現(xiàn)悉盆,代碼上也不能發(fā)現(xiàn)問題,后來忽然想到有沒可能是宿主app導(dǎo)致的馋吗,按照視頻中宿主調(diào)試看看焕盟,果然在“斗魚app”里面彈出鍵盤[UIView appearance].exclusiveTouch = YES,全局圖層的點擊事件被開啟了互斥宏粤,在其它地方彈出鍵盤就是好的脚翘,這意味著宿主app內(nèi)部對于UIAppearance做的一些設(shè)置,會同步生效在鍵盤上
解決方案就是

// 在鍵盤主Controller的聲明周期方法里

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    // 坑爹 有的宿主程序(斗魚)用下列代碼開啟了互斥 竟然鍵盤里也被開啟了 會導(dǎo)致多點觸控失效....
    // 這里為了確保 關(guān)閉touch事件互斥 放在鍵盤出現(xiàn)時執(zhí)行
    if ([UIView appearance].exclusiveTouch == YES) {
        [UIView appearance].exclusiveTouch = NO;
    }
    // 可以記錄一個標(biāo)志位 如果宿主開啟了互斥  這里臨時關(guān)閉  在viewDidDisappear里在開啟 確保不影響宿主APP


    // 對于宿主app 其實一般開啟UIButton或UIControl的事件互斥就夠了
    // 如:      [UIButton appearance].exclusiveTouch = YES;
}


7. 鍵盤inputView的寬度和UIScreen的寬度不一致

導(dǎo)致了鍵盤布局寬度超出屏幕绍哎,如下圖

image.png

這個主要是宿主App導(dǎo)致的来农,前段時間發(fā)現(xiàn)在"IT橙子"這個app里面彈出鍵盤時,鍵盤的寬度撐出了屏幕崇堰,通過對比百度/搜狗輸入法沃于,要么也是撐出屏幕,要么鍵盤彈出時也是撐出屏幕海诲,彈出后抖動了一下才恢復(fù)正常繁莹,如下圖
hirsa-u72xj.gif

解決方案
在鍵盤VC的viewDidAppear方法里,重新獲取一次inputView的寬度特幔,和已經(jīng)計算好的布局對比咨演,如果寬度發(fā)生變化,就重新計算布局并刷新蚯斯,唯一的弊端就是會抖一下(百度輸入法也會)薄风,反正是極少情況才會出現(xiàn)零院。沒有深究宿主APP干了啥會導(dǎo)致這個問題??????

8. 獲取鍵盤彈出時的App包名(hostBundleID)

iOS16之前比較簡單

// 在鍵盤入口controller中(即UIInputViewController的子類)
[self.parentViewController valueForKey:@"_hostBundleID"]

iOS16上述方法獲取到的是nil,也沒查到相關(guān)解決方案村刨,看到xxx輸入法需要判斷包名的業(yè)務(wù)依然正常告抄,就逆向分析了下其代碼實現(xiàn)????,如下

#import <dlfcn.h>

+ (NSString *)hostBundleIDWithInputVC:(UIInputViewController *)vc {
    
    NSString *bundleID = nil;
    
    @try {
        bundleID = [vc.parentViewController valueForKey:@"_hostBundleID"];
    } @catch (NSException *exception) {
        NSLog(@"hostBundleID Get Failure 1 %@", exception);
    } @finally {
        
    }
    
    if(XMUtils.validString(bundleID) && ![bundleID isEqual:@"<null>"]) {
        return bundleID;
    }
    
    // 云控禁止xpc取法

    // xpc取法 逆向自xx輸入法 主要解決iOS16上獲取不到的問題
    @try {
        id hostPid = [vc.parentViewController valueForKey:@"_hostPID"];
        
        if (hostPid) {
            
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
            
            id serverIns = [NSClassFromString(@"PKService") performSelector:NSSelectorFromString(@"defaultService")];
            id lities = [serverIns performSelector:NSSelectorFromString(@"personalities")];

            id infos = [lities objectForKey:[NSBundle mainBundle].bundleIdentifier];
            
            id info = [infos objectForKey:hostPid];
            id con = [info performSelector:NSSelectorFromString(@"connection")];
            id xpcCon = [con performSelector:NSSelectorFromString(@"_xpcConnection")];
            
    #pragma clang diagnostic pop
            
            const char * (* cfunc)(id) = dlsym(RTLD_DEFAULT, "xpc_connection_copy_bundle_id");
            
            if (cfunc != nil && xpcCon != nil) {
                const char *res = cfunc(xpcCon);
                bundleID = [NSString stringWithUTF8String:res];
                return  bundleID;
            }
        }
    } @catch (NSException *exception) {
        NSLog(@"hostBundleID Get Failure 2 %@", exception);
    } @finally {
        
    }
   
    return nil;
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嵌牺,一起剝皮案震驚了整個濱河市打洼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌逆粹,老刑警劉巖募疮,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異僻弹,居然都是意外死亡阿浓,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門蹋绽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來芭毙,“玉大人,你說我怎么就攤上這事卸耘⊥硕兀” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵蚣抗,是天一觀的道長侈百。 經(jīng)常有香客問我,道長翰铡,這世上最難降的妖魔是什么钝域? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮锭魔,結(jié)果婚禮上例证,老公的妹妹穿的比我還像新娘。我一直安慰自己赂毯,他們只是感情好战虏,可當(dāng)我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著党涕,像睡著了一般烦感。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上膛堤,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天手趣,我揣著相機與錄音,去河邊找鬼。 笑死绿渣,一個胖子當(dāng)著我的面吹牛朝群,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播中符,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼姜胖,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了淀散?” 一聲冷哼從身側(cè)響起右莱,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎档插,沒想到半個月后慢蜓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡郭膛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年晨抡,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片则剃。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡耘柱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出忍级,到底是詐尸還是另有隱情帆谍,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布轴咱,位于F島的核電站,受9級特大地震影響烈涮,放射性物質(zhì)發(fā)生泄漏朴肺。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一坚洽、第九天 我趴在偏房一處隱蔽的房頂上張望戈稿。 院中可真熱鬧,春花似錦讶舰、人聲如沸鞍盗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽般甲。三九已至,卻和暖如春鹅颊,著一層夾襖步出監(jiān)牢的瞬間敷存,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工堪伍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留锚烦,地道東北人觅闽。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像涮俄,于是被迫代替她去往敵國和親蛉拙。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,925評論 2 344

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